From 2aa0fdd6b6251544321dfef963cef58350598d1b Mon Sep 17 00:00:00 2001 From: danielbarry Date: Fri, 20 Nov 2020 03:04:07 +1300 Subject: [PATCH] Added mbedTLS as a submodule (#64) Removed mbedTLS files and replaced them with a submodule --- .gitmodules | 4 + README.rst | 9 +- components/security/mbedtls | 1 + components/security/mbedtls/Config.in | 9 - components/security/mbedtls/aos.mk | 112 - components/security/mbedtls/bouffalo.mk | 98 - .../mbedtls/include/icrypto/ali_crypto.h | 334 - .../include/icrypto/ali_crypto_debug.h | 54 - .../include/icrypto/ali_crypto_types.h | 152 - .../security/mbedtls/include/icrypto/crypto.h | 129 - .../security/mbedtls/include/mbedtls/aes.h | 297 - .../mbedtls/include/mbedtls/aes_alt.h | 46 - .../security/mbedtls/include/mbedtls/aesni.h | 111 - .../security/mbedtls/include/mbedtls/asn1.h | 342 - .../mbedtls/include/mbedtls/asn1write.h | 239 - .../security/mbedtls/include/mbedtls/base64.h | 88 - .../security/mbedtls/include/mbedtls/bignum.h | 717 -- .../security/mbedtls/include/mbedtls/bn_mul.h | 885 -- .../security/mbedtls/include/mbedtls/certs.h | 99 - .../mbedtls/include/mbedtls/check_config.h | 675 -- .../security/mbedtls/include/mbedtls/cipher.h | 709 -- .../mbedtls/include/mbedtls/cipher_internal.h | 109 - .../security/mbedtls/include/mbedtls/cmac.h | 170 - .../security/mbedtls/include/mbedtls/config.h | 195 - .../mbedtls/include/mbedtls/ctr_drbg.h | 290 - .../security/mbedtls/include/mbedtls/debug.h | 238 - .../security/mbedtls/include/mbedtls/des.h | 306 - .../security/mbedtls/include/mbedtls/ecdh.h | 214 - .../security/mbedtls/include/mbedtls/ecdsa.h | 248 - .../security/mbedtls/include/mbedtls/ecp.h | 684 -- .../mbedtls/include/mbedtls/ecp_internal.h | 293 - .../mbedtls/include/mbedtls/entropy.h | 287 - .../mbedtls/include/mbedtls/entropy_poll.h | 109 - .../security/mbedtls/include/mbedtls/error.h | 107 - .../security/mbedtls/include/mbedtls/gcm.h | 316 - .../security/mbedtls/include/mbedtls/havege.h | 74 - .../mbedtls/include/mbedtls/hmac_drbg.h | 299 - .../mbedtls/include/mbedtls/mbedtls_ssl.h | 61 - .../security/mbedtls/include/mbedtls/md.h | 354 - .../security/mbedtls/include/mbedtls/md2.h | 136 - .../security/mbedtls/include/mbedtls/md5.h | 137 - .../mbedtls/include/mbedtls/md5_alt.h | 36 - .../mbedtls/include/mbedtls/md_internal.h | 114 - .../mbedtls/include/mbedtls/mycalloc.h | 5 - .../security/mbedtls/include/mbedtls/net.h | 31 - .../mbedtls/include/mbedtls/net_sockets.h | 225 - .../security/mbedtls/include/mbedtls/oid.h | 570 -- .../mbedtls/include/mbedtls/padlock.h | 107 - .../security/mbedtls/include/mbedtls/pem.h | 129 - .../security/mbedtls/include/mbedtls/pk.h | 620 -- .../mbedtls/include/mbedtls/pk_internal.h | 114 - .../security/mbedtls/include/mbedtls/pkcs11.h | 173 - .../security/mbedtls/include/mbedtls/pkcs5.h | 94 - .../mbedtls/include/mbedtls/platform.h | 305 - .../mbedtls/include/mbedtls/platform_alt.h | 27 - .../mbedtls/include/mbedtls/platform_time.h | 81 - .../security/mbedtls/include/mbedtls/rsa.h | 658 -- .../mbedtls/include/mbedtls/rsa_alt.h | 49 - .../security/mbedtls/include/mbedtls/sha1.h | 137 - .../mbedtls/include/mbedtls/sha1_alt.h | 36 - .../security/mbedtls/include/mbedtls/sha256.h | 157 - .../mbedtls/include/mbedtls/sha256_alt.h | 36 - .../security/mbedtls/include/mbedtls/sha512.h | 141 - .../security/mbedtls/include/mbedtls/ssl.h | 2559 ------ .../mbedtls/include/mbedtls/ssl_cache.h | 143 - .../include/mbedtls/ssl_ciphersuites.h | 321 - .../mbedtls/include/mbedtls/ssl_cookie.h | 108 - .../mbedtls/include/mbedtls/ssl_internal.h | 500 -- .../mbedtls/include/mbedtls/ssl_ticket.h | 135 - .../mbedtls/include/mbedtls/threading.h | 110 - .../mbedtls/include/mbedtls/threading_alt.h | 26 - .../security/mbedtls/include/mbedtls/timing.h | 141 - .../mbedtls/include/mbedtls/version.h | 111 - .../security/mbedtls/include/mbedtls/x509.h | 335 - .../mbedtls/include/mbedtls/x509_crl.h | 173 - .../mbedtls/include/mbedtls/x509_crt.h | 656 -- .../mbedtls/include/mbedtls/x509_csr.h | 298 - .../mbedtls/lib/ARM968E-S/libmbedtls.a.dbg | Bin 580266 -> 0 bytes .../lib/Cortex-M4/IAR/libmbedtls.a.dbg | Bin 415804 -> 0 bytes .../mbedtls/lib/Cortex-M4/KEIL/libmbedtls.lib | Bin 291896 -> 0 bytes .../lib/Cortex-M4/KEIL/libmbedtls.lib.dbg | Bin 319236 -> 0 bytes .../mbedtls/lib/Cortex-M4/libmbedtls.a.dbg | Bin 587578 -> 0 bytes .../mbedtls/lib/linux/libmbedtls.a.lwip | Bin 579622 -> 0 bytes .../mbedtls/lib/xtensa/libmbedtls.a.dbg | Bin 1003350 -> 0 bytes components/security/mbedtls/src/aes.c | 1494 ---- components/security/mbedtls/src/aesni.c | 464 - components/security/mbedtls/src/arc4.c | 205 - components/security/mbedtls/src/asn1parse.c | 393 - components/security/mbedtls/src/asn1write.c | 390 - components/security/mbedtls/src/base64.c | 293 - components/security/mbedtls/src/bignum.c | 2450 ------ components/security/mbedtls/src/blowfish.c | 656 -- components/security/mbedtls/src/camellia.c | 1072 --- components/security/mbedtls/src/ccm.c | 464 - components/security/mbedtls/src/certs.c | 351 - components/security/mbedtls/src/cipher.c | 925 -- components/security/mbedtls/src/cipher_wrap.c | 1500 ---- components/security/mbedtls/src/cmac.c | 1074 --- components/security/mbedtls/src/ctr_drbg.c | 595 -- components/security/mbedtls/src/debug.c | 397 - components/security/mbedtls/src/des.c | 1061 --- components/security/mbedtls/src/dhm.c | 627 -- components/security/mbedtls/src/ecdh.c | 264 - components/security/mbedtls/src/ecdsa.c | 448 - components/security/mbedtls/src/ecjpake.c | 1103 --- components/security/mbedtls/src/ecp.c | 2217 ----- components/security/mbedtls/src/ecp_curves.c | 1329 --- components/security/mbedtls/src/entropy.c | 659 -- .../security/mbedtls/src/entropy_poll.c | 275 - components/security/mbedtls/src/error.c | 707 -- components/security/mbedtls/src/gcm.c | 952 -- components/security/mbedtls/src/havege.c | 245 - components/security/mbedtls/src/hmac_drbg.c | 529 -- components/security/mbedtls/src/mbedtls_alt.c | 883 -- components/security/mbedtls/src/mbedtls_net.c | 427 - components/security/mbedtls/src/mbedtls_ssl.c | 406 - components/security/mbedtls/src/md.c | 473 - components/security/mbedtls/src/md2.c | 288 - components/security/mbedtls/src/md4.c | 384 - components/security/mbedtls/src/md5.c | 404 - components/security/mbedtls/src/md_wrap.c | 749 -- .../mbedtls/src/memory_buffer_alloc.c | 745 -- components/security/mbedtls/src/mycalloc.c | 9 - components/security/mbedtls/src/net_sockets.c | 593 -- components/security/mbedtls/src/oid.c | 710 -- components/security/mbedtls/src/padlock.c | 170 - components/security/mbedtls/src/pem.c | 505 -- components/security/mbedtls/src/pk.c | 383 - components/security/mbedtls/src/pk_wrap.c | 622 -- components/security/mbedtls/src/pkcs11.c | 240 - components/security/mbedtls/src/pkcs12.c | 365 - components/security/mbedtls/src/pkcs5.c | 406 - components/security/mbedtls/src/pkparse.c | 1399 --- components/security/mbedtls/src/pkwrite.c | 439 - components/security/mbedtls/src/platform.c | 307 - components/security/mbedtls/src/ripemd160.c | 467 - components/security/mbedtls/src/rsa.c | 1738 ---- components/security/mbedtls/src/sha1.c | 449 - components/security/mbedtls/src/sha256.c | 459 - components/security/mbedtls/src/sha512.c | 514 -- components/security/mbedtls/src/ssl_cache.c | 326 - .../security/mbedtls/src/ssl_ciphersuites.c | 1872 ---- components/security/mbedtls/src/ssl_cli.c | 3405 ------- components/security/mbedtls/src/ssl_cookie.c | 260 - components/security/mbedtls/src/ssl_srv.c | 3926 --------- components/security/mbedtls/src/ssl_ticket.c | 489 -- components/security/mbedtls/src/ssl_tls.c | 7807 ----------------- components/security/mbedtls/src/threading.c | 146 - components/security/mbedtls/src/timing.c | 522 -- components/security/mbedtls/src/version.c | 50 - .../security/mbedtls/src/version_features.c | 677 -- components/security/mbedtls/src/x509.c | 1146 --- components/security/mbedtls/src/x509_create.c | 340 - components/security/mbedtls/src/x509_crl.c | 725 -- components/security/mbedtls/src/x509_crt.c | 2463 ------ components/security/mbedtls/src/x509_csr.c | 425 - .../security/mbedtls/src/x509write_crt.c | 459 - .../security/mbedtls/src/x509write_csr.c | 259 - components/security/mbedtls/src/xtea.c | 281 - components/security/mbedtls/version | 2 - 160 files changed, 13 insertions(+), 82438 deletions(-) create mode 160000 components/security/mbedtls delete mode 100644 components/security/mbedtls/Config.in delete mode 100644 components/security/mbedtls/aos.mk delete mode 100644 components/security/mbedtls/bouffalo.mk delete mode 100644 components/security/mbedtls/include/icrypto/ali_crypto.h delete mode 100644 components/security/mbedtls/include/icrypto/ali_crypto_debug.h delete mode 100644 components/security/mbedtls/include/icrypto/ali_crypto_types.h delete mode 100644 components/security/mbedtls/include/icrypto/crypto.h delete mode 100644 components/security/mbedtls/include/mbedtls/aes.h delete mode 100644 components/security/mbedtls/include/mbedtls/aes_alt.h delete mode 100644 components/security/mbedtls/include/mbedtls/aesni.h delete mode 100644 components/security/mbedtls/include/mbedtls/asn1.h delete mode 100644 components/security/mbedtls/include/mbedtls/asn1write.h delete mode 100644 components/security/mbedtls/include/mbedtls/base64.h delete mode 100644 components/security/mbedtls/include/mbedtls/bignum.h delete mode 100644 components/security/mbedtls/include/mbedtls/bn_mul.h delete mode 100644 components/security/mbedtls/include/mbedtls/certs.h delete mode 100644 components/security/mbedtls/include/mbedtls/check_config.h delete mode 100644 components/security/mbedtls/include/mbedtls/cipher.h delete mode 100644 components/security/mbedtls/include/mbedtls/cipher_internal.h delete mode 100644 components/security/mbedtls/include/mbedtls/cmac.h delete mode 100644 components/security/mbedtls/include/mbedtls/config.h delete mode 100644 components/security/mbedtls/include/mbedtls/ctr_drbg.h delete mode 100644 components/security/mbedtls/include/mbedtls/debug.h delete mode 100644 components/security/mbedtls/include/mbedtls/des.h delete mode 100644 components/security/mbedtls/include/mbedtls/ecdh.h delete mode 100644 components/security/mbedtls/include/mbedtls/ecdsa.h delete mode 100644 components/security/mbedtls/include/mbedtls/ecp.h delete mode 100644 components/security/mbedtls/include/mbedtls/ecp_internal.h delete mode 100644 components/security/mbedtls/include/mbedtls/entropy.h delete mode 100644 components/security/mbedtls/include/mbedtls/entropy_poll.h delete mode 100644 components/security/mbedtls/include/mbedtls/error.h delete mode 100644 components/security/mbedtls/include/mbedtls/gcm.h delete mode 100644 components/security/mbedtls/include/mbedtls/havege.h delete mode 100644 components/security/mbedtls/include/mbedtls/hmac_drbg.h delete mode 100644 components/security/mbedtls/include/mbedtls/mbedtls_ssl.h delete mode 100644 components/security/mbedtls/include/mbedtls/md.h delete mode 100644 components/security/mbedtls/include/mbedtls/md2.h delete mode 100644 components/security/mbedtls/include/mbedtls/md5.h delete mode 100644 components/security/mbedtls/include/mbedtls/md5_alt.h delete mode 100644 components/security/mbedtls/include/mbedtls/md_internal.h delete mode 100644 components/security/mbedtls/include/mbedtls/mycalloc.h delete mode 100644 components/security/mbedtls/include/mbedtls/net.h delete mode 100644 components/security/mbedtls/include/mbedtls/net_sockets.h delete mode 100644 components/security/mbedtls/include/mbedtls/oid.h delete mode 100644 components/security/mbedtls/include/mbedtls/padlock.h delete mode 100644 components/security/mbedtls/include/mbedtls/pem.h delete mode 100644 components/security/mbedtls/include/mbedtls/pk.h delete mode 100644 components/security/mbedtls/include/mbedtls/pk_internal.h delete mode 100644 components/security/mbedtls/include/mbedtls/pkcs11.h delete mode 100644 components/security/mbedtls/include/mbedtls/pkcs5.h delete mode 100644 components/security/mbedtls/include/mbedtls/platform.h delete mode 100644 components/security/mbedtls/include/mbedtls/platform_alt.h delete mode 100644 components/security/mbedtls/include/mbedtls/platform_time.h delete mode 100644 components/security/mbedtls/include/mbedtls/rsa.h delete mode 100644 components/security/mbedtls/include/mbedtls/rsa_alt.h delete mode 100644 components/security/mbedtls/include/mbedtls/sha1.h delete mode 100644 components/security/mbedtls/include/mbedtls/sha1_alt.h delete mode 100644 components/security/mbedtls/include/mbedtls/sha256.h delete mode 100644 components/security/mbedtls/include/mbedtls/sha256_alt.h delete mode 100644 components/security/mbedtls/include/mbedtls/sha512.h delete mode 100644 components/security/mbedtls/include/mbedtls/ssl.h delete mode 100644 components/security/mbedtls/include/mbedtls/ssl_cache.h delete mode 100644 components/security/mbedtls/include/mbedtls/ssl_ciphersuites.h delete mode 100644 components/security/mbedtls/include/mbedtls/ssl_cookie.h delete mode 100644 components/security/mbedtls/include/mbedtls/ssl_internal.h delete mode 100644 components/security/mbedtls/include/mbedtls/ssl_ticket.h delete mode 100644 components/security/mbedtls/include/mbedtls/threading.h delete mode 100644 components/security/mbedtls/include/mbedtls/threading_alt.h delete mode 100644 components/security/mbedtls/include/mbedtls/timing.h delete mode 100644 components/security/mbedtls/include/mbedtls/version.h delete mode 100644 components/security/mbedtls/include/mbedtls/x509.h delete mode 100644 components/security/mbedtls/include/mbedtls/x509_crl.h delete mode 100644 components/security/mbedtls/include/mbedtls/x509_crt.h delete mode 100644 components/security/mbedtls/include/mbedtls/x509_csr.h delete mode 100644 components/security/mbedtls/lib/ARM968E-S/libmbedtls.a.dbg delete mode 100755 components/security/mbedtls/lib/Cortex-M4/IAR/libmbedtls.a.dbg delete mode 100755 components/security/mbedtls/lib/Cortex-M4/KEIL/libmbedtls.lib delete mode 100755 components/security/mbedtls/lib/Cortex-M4/KEIL/libmbedtls.lib.dbg delete mode 100644 components/security/mbedtls/lib/Cortex-M4/libmbedtls.a.dbg delete mode 100644 components/security/mbedtls/lib/linux/libmbedtls.a.lwip delete mode 100644 components/security/mbedtls/lib/xtensa/libmbedtls.a.dbg delete mode 100644 components/security/mbedtls/src/aes.c delete mode 100644 components/security/mbedtls/src/aesni.c delete mode 100644 components/security/mbedtls/src/arc4.c delete mode 100644 components/security/mbedtls/src/asn1parse.c delete mode 100644 components/security/mbedtls/src/asn1write.c delete mode 100644 components/security/mbedtls/src/base64.c delete mode 100644 components/security/mbedtls/src/bignum.c delete mode 100644 components/security/mbedtls/src/blowfish.c delete mode 100644 components/security/mbedtls/src/camellia.c delete mode 100644 components/security/mbedtls/src/ccm.c delete mode 100644 components/security/mbedtls/src/certs.c delete mode 100644 components/security/mbedtls/src/cipher.c delete mode 100644 components/security/mbedtls/src/cipher_wrap.c delete mode 100644 components/security/mbedtls/src/cmac.c delete mode 100644 components/security/mbedtls/src/ctr_drbg.c delete mode 100644 components/security/mbedtls/src/debug.c delete mode 100644 components/security/mbedtls/src/des.c delete mode 100644 components/security/mbedtls/src/dhm.c delete mode 100644 components/security/mbedtls/src/ecdh.c delete mode 100644 components/security/mbedtls/src/ecdsa.c delete mode 100644 components/security/mbedtls/src/ecjpake.c delete mode 100644 components/security/mbedtls/src/ecp.c delete mode 100644 components/security/mbedtls/src/ecp_curves.c delete mode 100644 components/security/mbedtls/src/entropy.c delete mode 100644 components/security/mbedtls/src/entropy_poll.c delete mode 100644 components/security/mbedtls/src/error.c delete mode 100644 components/security/mbedtls/src/gcm.c delete mode 100644 components/security/mbedtls/src/havege.c delete mode 100644 components/security/mbedtls/src/hmac_drbg.c delete mode 100644 components/security/mbedtls/src/mbedtls_alt.c delete mode 100644 components/security/mbedtls/src/mbedtls_net.c delete mode 100644 components/security/mbedtls/src/mbedtls_ssl.c delete mode 100644 components/security/mbedtls/src/md.c delete mode 100644 components/security/mbedtls/src/md2.c delete mode 100644 components/security/mbedtls/src/md4.c delete mode 100644 components/security/mbedtls/src/md5.c delete mode 100644 components/security/mbedtls/src/md_wrap.c delete mode 100644 components/security/mbedtls/src/memory_buffer_alloc.c delete mode 100644 components/security/mbedtls/src/mycalloc.c delete mode 100644 components/security/mbedtls/src/net_sockets.c delete mode 100644 components/security/mbedtls/src/oid.c delete mode 100644 components/security/mbedtls/src/padlock.c delete mode 100644 components/security/mbedtls/src/pem.c delete mode 100644 components/security/mbedtls/src/pk.c delete mode 100644 components/security/mbedtls/src/pk_wrap.c delete mode 100644 components/security/mbedtls/src/pkcs11.c delete mode 100644 components/security/mbedtls/src/pkcs12.c delete mode 100644 components/security/mbedtls/src/pkcs5.c delete mode 100644 components/security/mbedtls/src/pkparse.c delete mode 100644 components/security/mbedtls/src/pkwrite.c delete mode 100644 components/security/mbedtls/src/platform.c delete mode 100644 components/security/mbedtls/src/ripemd160.c delete mode 100644 components/security/mbedtls/src/rsa.c delete mode 100644 components/security/mbedtls/src/sha1.c delete mode 100644 components/security/mbedtls/src/sha256.c delete mode 100644 components/security/mbedtls/src/sha512.c delete mode 100644 components/security/mbedtls/src/ssl_cache.c delete mode 100644 components/security/mbedtls/src/ssl_ciphersuites.c delete mode 100644 components/security/mbedtls/src/ssl_cli.c delete mode 100644 components/security/mbedtls/src/ssl_cookie.c delete mode 100644 components/security/mbedtls/src/ssl_srv.c delete mode 100644 components/security/mbedtls/src/ssl_ticket.c delete mode 100644 components/security/mbedtls/src/ssl_tls.c delete mode 100644 components/security/mbedtls/src/threading.c delete mode 100644 components/security/mbedtls/src/timing.c delete mode 100644 components/security/mbedtls/src/version.c delete mode 100644 components/security/mbedtls/src/version_features.c delete mode 100644 components/security/mbedtls/src/x509.c delete mode 100644 components/security/mbedtls/src/x509_create.c delete mode 100644 components/security/mbedtls/src/x509_crl.c delete mode 100644 components/security/mbedtls/src/x509_crt.c delete mode 100644 components/security/mbedtls/src/x509_csr.c delete mode 100644 components/security/mbedtls/src/x509write_crt.c delete mode 100644 components/security/mbedtls/src/x509write_csr.c delete mode 100644 components/security/mbedtls/src/xtea.c delete mode 100644 components/security/mbedtls/version diff --git a/.gitmodules b/.gitmodules index 6d2ccfcc..871889a9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "docs"] path = docs url = https://github.com/pine64/bl602-docs.git + +[submodule "components/security/mbedtls"] + path = components/security/mbedtls + url = https://github.com/ARMmbed/mbedtls diff --git a/README.rst b/README.rst index 4e1433c2..799bf124 100755 --- a/README.rst +++ b/README.rst @@ -7,7 +7,8 @@ This repository contains the Pine64 fork of Bouffalo Lab's SDK for their BL602 Wi-Fi/BLE Combo RISC-V SoC. Documentation, including upstream documentation, translations, mirrored technical documentation, and original reverse engineered documentation is at `bl602-docs `_, which -is cloned as a submodule of this repository at ``docs``. Use `git submodule update --init` to initialize the submodule. +is cloned as a submodule of this repository at ``docs``. Use +`git submodule update --init` to initialize the submodule. This repository is the central focus of Pine64's `Nutcracker Challenge `_. @@ -18,6 +19,12 @@ You can find a lot of documentation on `PINE64 Documentation Website -#include -#include - - - -#if CONFIG_DBG_CRYPT -#ifndef PLATFORM_ANDROID -#define ALI_CRYPTO_DBG_E(_f, ...) \ - printf("E %s %d: "_f, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#define ALI_CRYPTO_DBG_I(_f, ...) \ - printf("I %s %d: "_f, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#else /* PLATFORM_ANDROID */ -#include -#define __LOG_TAG__ "ICRYPTO_LOG" - -#define LOG_INF(...) __android_log_print( \ - ANDROID_LOG_INFO, \ - __LOG_TAG__, \ - __VA_ARGS__) - -#define ALI_CRYPTO_DBG_E(_f, ...) \ - LOG_INF("E %s %d: "_f, __FUNCTION__, __LINE__, ##_VA_ARGS__) -#define ALI_CRYPTO_DBG_I(_f, ...) \ - LOG_INF("I %s %d: "_f, __FUNCTION__, __LINE__, ##_VA_ARGS__) -#endif /* PLATFORM_ANDROID */ - -#else /* CONFIG_DBG_CRYPT */ -#define ALI_CRYPTO_DBG_E(_f, _a...) -#define ALI_CRYPTO_DBG_I(_f, _a...) -#endif /* CONFIG_DBG_CRYPT */ - -#define PRINT_RET(_ret, _f, ...) \ - do { \ - ALI_CRYPTO_DBG_E(_f, ##__VA_ARGS__); \ - return (ali_crypto_result)_ret; \ - } while (0); - -#define GO_RET(_ret, _f, ...) \ - do { \ - ALI_CRYPTO_DBG_E(_f, ##__VA_ARGS__); \ - result = (ali_crypto_result)_ret; \ - goto _OUT; \ - } while (0); - - - -#endif /* _ALI_CRYPTO_DEBUG_H_ */ diff --git a/components/security/mbedtls/include/icrypto/ali_crypto_types.h b/components/security/mbedtls/include/icrypto/ali_crypto_types.h deleted file mode 100644 index 0d99d9a1..00000000 --- a/components/security/mbedtls/include/icrypto/ali_crypto_types.h +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright (C) 2017 Alibaba Group Holding Limited. - */ - -#ifndef _ALI_CRYPTO_TYPES_H_ -#define _ALI_CRYPTO_TYPES_H_ - -#include -#include /* for size_t */ -#include - -#if 0 -typedef unsigned char bool; -#endif - -#ifndef false -#define false (0) -#endif - -#ifndef true -#define true (1) -#endif - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#define UNUSED(expr) do { (void)(expr); } while (0) - -typedef enum _ali_crypto_result { - ALI_CRYPTO_ERROR = (int)0xffff0000, /* Generic Error */ - ALI_CRYPTO_NOSUPPORT, /* Scheme not support */ - ALI_CRYPTO_INVALID_KEY, /* Invalid Key in asymmetric scheme: RSA/DSA/ECCP/DH etc */ - ALI_CRYPTO_INVALID_TYPE, /* Invalid aes_type/des_type/authenc_type/hash_type/cbcmac_type/cmac_type */ - ALI_CRYPTO_INVALID_CONTEXT, /* Invalid context in multi-thread cipher/authenc/mac/hash etc */ - ALI_CRYPTO_INVALID_PADDING, /* Invalid sym_padding/rsassa_padding/rsaes_padding */ - ALI_CRYPTO_INVALID_AUTHENTICATION, /* Invalid authentication in AuthEnc(AES-CCM/AES-GCM)/asymmetric verify(RSA/DSA/ECCP DSA) */ - ALI_CRYPTO_INVALID_ARG, /* Invalid arguments */ - ALI_CRYPTO_INVALID_PACKET, /* Invalid packet in asymmetric enc/dec(RSA) */ - ALI_CRYPTO_LENGTH_ERR, /* Invalid Length in arguments */ - ALI_CRYPTO_OUTOFMEM, /* Memory alloc NULL */ - ALI_CRYPTO_SHORT_BUFFER, /* Output buffer is too short to store result */ - ALI_CRYPTO_NULL, /* NULL pointer in arguments */ - ALI_CRYPTO_ERR_STATE, /* Bad state in mulit-thread cipher/authenc/mac/hash etc */ - ALI_CRYPTO_SUCCESS = 0, /* Success */ -} ali_crypto_result; - -#define AES_BLOCK_SIZE 16 /* don't change this value,since AES only support 16 byte block size */ -#define AES_IV_SIZE 16 -#define SM4_BLOCK_SIZE 16 -#define SM4_IV_SIZE 16 -#define DES_BLOCK_SIZE 8 -#define DES_IV_SIZE 8 - -/* hash constants */ -#if (CONFIG_HAL_SHA512 || CONFIG_SAL_SHA512) -#define MAX_HASH_SIZE 64 /* longest known is SHA512 */ -#else -#define MAX_HASH_SIZE 32 /* longest known is SHA256 or less */ -#endif - -/* RSA constants */ -#define ALI_CRYPTO_RSA_PUBLIC 0 -#define ALI_CRYPTO_RSA_PRIVATE 1 - -#define ALI_CRYPTO_RSA_PKCS_V15 0 -#define ALI_CRYPTO_RSA_PKCS_V21 1 - -#define ALI_CRYPTO_RSA_SIGN 1 -#define ALI_CRYPTO_RSA_CRYPT 2 - -typedef enum _sym_padding_t { - SYM_NOPAD = 0, - SYM_PKCS5_PAD = 1, - SYM_ZERO_PAD = 2, -} sym_padding_t; - -typedef enum _aes_type_t { - AES_ECB = 0, - AES_CBC = 1, - AES_CTR = 2, - AES_CTS = 3, - AES_XTS = 4, - AES_CFB8 = 6, - AES_CFB128 = 7, -} aes_type_t; - -typedef enum _sm4_type_t { - SM4_ECB = 0, - SM4_CBC = 1, -} sm4_type_t; - -typedef enum _des_type_t { - DES_ECB = 0, - DES_CBC = 1, - DES3_ECB = 2, - DES3_CBC = 3, -} des_type_t; - -typedef enum _hash_type_t { - HASH_NONE = 0, - SHA1 = 1, - SHA224 = 2, - SHA256 = 3, - SHA384 = 4, - SHA512 = 5, - MD5 = 6, - SM3 = 7, -} hash_type_t; - -enum { - MD5_HASH_SIZE = 16, - SHA1_HASH_SIZE = 20, - SHA224_HASH_SIZE = 28, - SHA256_HASH_SIZE = 32, - SM3_HASH_SIZE = 32, - SHA384_HASH_SIZE = 48, - SHA512_HASH_SIZE = 64, -}; - -typedef enum _rsa_key_attr_t { - RSA_MODULUS = 0x130, - RSA_PUBLIC_EXPONENT = 0x230, - RSA_PRIVATE_EXPONENT = 0x330, - RSA_PRIME1 = 0x430, - RSA_PRIME2 = 0x530, - RSA_EXPONENT1 = 0x630, - RSA_EXPONENT2 = 0x730, - RSA_COEFFICIENT = 0x830, -} rsa_key_attr_t; - -typedef enum _rsa_pad_type_t { - RSA_NOPAD = 0, - - /* encrypt */ - RSAES_PKCS1_V1_5 = 10, - RSAES_PKCS1_OAEP_MGF1 = 11, - - /* sign */ - RSASSA_PKCS1_V1_5 = 20, - RSASSA_PKCS1_PSS_MGF1 = 21, -} rsa_pad_type_t; - -enum { - CRYPTO_STATUS_CLEAN = 0, - CRYPTO_STATUS_INITIALIZED = 1, - CRYPTO_STATUS_PROCESSING = 2, - CRYPTO_STATUS_FINISHED = 3, -}; - - -#endif /* _ALI_CRYPTO_TYPES_H_ */ diff --git a/components/security/mbedtls/include/icrypto/crypto.h b/components/security/mbedtls/include/icrypto/crypto.h deleted file mode 100644 index b0f0c2cb..00000000 --- a/components/security/mbedtls/include/icrypto/crypto.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef _CRYPTO_H_ -#define _CRYPTO_H_ -#include "ali_crypto.h" - -/* aes */ -#define crypto_aes_get_ctx_size(type, size) \ - ali_aes_get_ctx_size((type), (size)) - -#define crypto_aes_init(type, is_enc, key1, key2, keybytes, iv, contex) \ - ali_aes_init(type, is_enc, key1, key2, keybytes, iv, contex) - -#define crypto_aes_process(src, dst, size, context) \ - ali_aes_process(src, dst, size, context) - -#define crypto_aes_finish(src, src_size, dst, dst_size, padding, context) \ - ali_aes_finish(src, src_size, dst, dst_size, padding, context) - -#define crypto_aes_reset(context) \ - ali_aes_reset(context) - -/* des */ -#define crypto_des_get_ctx_size(type, size) \ - ali_des_get_ctx_size(type, size) - -#define crypto_des_init(type, is_enc, key, keybytes, iv, context) \ - ali_des_init(type, is_enc, key, keybytes, iv, context) - -#define crypto_des_process(src, dst,size, context) \ - ali_des_process(src, dst,size, context) - -#define crypto_des_finish(src, src_size, dst, dst_size, padding, context) \ - ali_des_finish(src, src_size, dst, dst_size, padding, context) - -#define crypto_des_reset(context) \ - ali_des_reset(context) - -/* hash */ -#define crypto_hash_get_ctx_size(type, size) \ - ali_hash_get_ctx_size(type, size) - -#define crypto_hash_init(type, context) \ - ali_hash_init(type, context) - -#define crypto_hash_update(src, size, context) \ - ali_hash_update(src, size, context) - -#define crypto_hash_final(dgst, context) \ - ali_hash_final(dgst, context) - -#define crypto_hash_reset(context) \ - ali_hash_reset(context) - -#define crypto_hash_digest(type, src, size, dgst) \ - ali_hash_digest(type, src, size, dgst) - -/* hmac */ -#define crypto_hmac_get_ctx_size(type, size) \ - ali_hmac_get_ctx_size(type, size) - -#define crypto_hmac_init(type, key, keybytes, context) \ - ali_hmac_init(type, key, keybytes, context) - -#define crypto_hmac_update(src, size, context) \ - ali_hmac_update(src, size, context) - -#define crypto_hmac_final(dgst, context) \ - ali_hmac_final(dgst, context) - -#define crypto_hmac_reset(context) \ - ali_hmac_reset(context) - -#define crypto_hmac_digest(type, key, keybytes, src, size, dgst) \ - ali_hmac_digest(type, key, keybytes, src, size, dgst) - -/* rsa */ -#define crypto_rsa_get_keypair_size(keybits, size) \ - ali_rsa_get_keypair_size(keybits, size) - -#define crypto_rsa_get_pubkey_size(keybits, size) \ - ali_rsa_get_pubkey_size(keybits, size) - -#define crypto_rsa_init_keypair(keybits, n, n_size, e, e_size, d, d_size, \ - p, p_size, q, q_size, dp, dp_size, dq, \ - dq_size, qp, qp_size, keypair) \ - ali_rsa_init_keypair(keybits, n, n_size, e, e_size, d, d_size, \ - p, p_size, q, q_size, dp, dp_size, dq, \ - dq_size, qp, qp_size, keypair) - -#define crypto_rsa_init_pubkey(keybits, n, n_size, e, e_size, pubkey) \ - ali_rsa_init_pubkey(keybits, n, n_size, e, e_size, pubkey) - -#define crypto_rsa_gen_keypair(keybits, e, e_size, keypair) \ - ali_rsa_gen_keypair(keybits, e, e_size, keypair) - -#define crypto_rsa_get_key_attr(attr, keypair, buffer, size) \ - ali_rsa_get_key_attr(attr, keypair, buffer, size) - -#define crypto_rsa_public_encrypt(pub_key, src, src_size, \ - dst, dst_size, padding) \ - ali_rsa_public_encrypt(pub_key, src, src_size, \ - dst, dst_size, padding) - -#define crypto_rsa_private_decrypt(priv_key, src, src_size, \ - dst, dst_size, padding) \ - ali_rsa_private_decrypt(priv_key, src, src_size, \ - dst, dst_size, padding) - -#define crypto_rsa_sign(priv_key, dig, dig_size, sig, sig_size, padding) \ - ali_rsa_sign(priv_key, dig, dig_size, sig, sig_size, padding) - -#define crypto_rsa_verify(pub_key, dig, dig_size, sig, \ - sig_size, padding, result) \ - ali_rsa_verify(pub_key, dig, dig_size, sig, \ - sig_size, padding, result) - -/* random number */ -#define crypto_seed(seed, seed_len) \ - ali_seed(seed, seed_len) - -#define crypto_rand_gen(buf, len) \ - ali_rand_gen(buf, len) - -#define crypto_init() \ - ali_crypto_init() - -#define crypto_cleanup() \ - ali_crypto_cleanup() - -#endif /* _CRYPTO_H_ */ diff --git a/components/security/mbedtls/include/mbedtls/aes.h b/components/security/mbedtls/include/mbedtls/aes.h deleted file mode 100644 index a36e825a..00000000 --- a/components/security/mbedtls/include/mbedtls/aes.h +++ /dev/null @@ -1,297 +0,0 @@ -/** - * \file aes.h - * - * \brief AES block cipher - * - * 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) - */ -#ifndef MBEDTLS_AES_H -#define MBEDTLS_AES_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -/* padlock.c and aesni.c rely on these values! */ -#define MBEDTLS_AES_ENCRYPT 1 -#define MBEDTLS_AES_DECRYPT 0 - -#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ -#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ - -#if !defined(MBEDTLS_AES_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief AES context structure - * - * \note buf is able to hold 32 extra bytes, which can be used: - * - for alignment purposes if VIA padlock is used, and/or - * - to simplify key expansion in the 256-bit case by - * generating an extra round key - */ -typedef struct -{ - int nr; /*!< number of rounds */ - uint32_t *rk; /*!< AES round keys */ - uint32_t buf[68]; /*!< unaligned data */ -} -mbedtls_aes_context; - -/** - * \brief Initialize AES context - * - * \param ctx AES context to be initialized - */ -void mbedtls_aes_init( mbedtls_aes_context *ctx ); - -/** - * \brief Clear AES context - * - * \param ctx AES context to be cleared - */ -void mbedtls_aes_free( mbedtls_aes_context *ctx ); - -/** - * \brief AES key schedule (encryption) - * - * \param ctx AES context to be initialized - * \param key encryption key - * \param keybits must be 128, 192 or 256 - * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH - */ -int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ); - -/** - * \brief AES key schedule (decryption) - * - * \param ctx AES context to be initialized - * \param key decryption key - * \param keybits must be 128, 192 or 256 - * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH - */ -int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ); - -/** - * \brief AES-ECB block encryption/decryption - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if successful - */ -int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief AES-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH - */ -int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/** - * \brief AES-CFB128 buffer encryption/decryption. - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief AES-CFB8 buffer encryption/decryption. - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/** - * \brief AES-CTR buffer encryption/decryption - * - * Warning: You have to keep the maximum use of your counter in mind! - * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. - * - * \param ctx AES context - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful - */ -int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -/** - * \brief Internal AES block encryption function - * (Only exposed to allow overriding it, - * see MBEDTLS_AES_ENCRYPT_ALT) - * - * \param ctx AES context - * \param input Plaintext block - * \param output Output (ciphertext) block - */ -void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief Internal AES block decryption function - * (Only exposed to allow overriding it, - * see MBEDTLS_AES_DECRYPT_ALT) - * - * \param ctx AES context - * \param input Ciphertext block - * \param output Output (plaintext) block - */ -void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_AES_ALT */ -#include "aes_alt.h" -#endif /* MBEDTLS_AES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_aes_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* aes.h */ diff --git a/components/security/mbedtls/include/mbedtls/aes_alt.h b/components/security/mbedtls/include/mbedtls/aes_alt.h deleted file mode 100644 index 126071cd..00000000 --- a/components/security/mbedtls/include/mbedtls/aes_alt.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef MBEDTLS_AES_ALT_H -#define MBEDTLS_AES_ALT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define AES_STATUS_NONE 0 -#define AES_STATUS_INIT 1 -#define AES_STATUS_PROCESS 2 - -typedef struct -{ - size_t reset; - size_t status; - uint8_t key[32]; - size_t key_len; - void *ali_ctx; -} mbedtls_aes_context; - -void mbedtls_aes_init_alt( mbedtls_aes_context *ctx ); -void mbedtls_aes_free_alt( mbedtls_aes_context *ctx ); - -int mbedtls_aes_setkey_enc_alt( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ); -int mbedtls_aes_setkey_dec_alt( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ); - -int mbedtls_aes_crypt_ecb_alt( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); -int mbedtls_aes_crypt_cbc_alt( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_AES_ALT_H */ diff --git a/components/security/mbedtls/include/mbedtls/aesni.h b/components/security/mbedtls/include/mbedtls/aesni.h deleted file mode 100644 index b1b7f1cd..00000000 --- a/components/security/mbedtls/include/mbedtls/aesni.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file aesni.h - * - * \brief AES-NI for hardware AES acceleration on some Intel processors - * - * 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) - */ -#ifndef MBEDTLS_AESNI_H -#define MBEDTLS_AESNI_H - -#include "aes.h" - -#define MBEDTLS_AESNI_AES 0x02000000u -#define MBEDTLS_AESNI_CLMUL 0x00000002u - -#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ - ( defined(__amd64__) || defined(__x86_64__) ) && \ - ! defined(MBEDTLS_HAVE_X86_64) -#define MBEDTLS_HAVE_X86_64 -#endif - -#if defined(MBEDTLS_HAVE_X86_64) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief AES-NI features detection routine - * - * \param what The feature to detect - * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) - * - * \return 1 if CPU has support for the feature, 0 otherwise - */ -int mbedtls_aesni_has_support( unsigned int what ); - -/** - * \brief AES-NI AES-ECB block en(de)cryption - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 on success (cannot fail) - */ -int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief GCM multiplication: c = a * b in GF(2^128) - * - * \param c Result - * \param a First operand - * \param b Second operand - * - * \note Both operands and result are bit strings interpreted as - * elements of GF(2^128) as per the GCM spec. - */ -void mbedtls_aesni_gcm_mult( unsigned char c[16], - const unsigned char a[16], - const unsigned char b[16] ); - -/** - * \brief Compute decryption round keys from encryption round keys - * - * \param invkey Round keys for the equivalent inverse cipher - * \param fwdkey Original round keys (for encryption) - * \param nr Number of rounds (that is, number of round keys minus one) - */ -void mbedtls_aesni_inverse_key( unsigned char *invkey, - const unsigned char *fwdkey, int nr ); - -/** - * \brief Perform key expansion (for encryption) - * - * \param rk Destination buffer where the round keys are written - * \param key Encryption key - * \param bits Key size in bits (must be 128, 192 or 256) - * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH - */ -int mbedtls_aesni_setkey_enc( unsigned char *rk, - const unsigned char *key, - size_t bits ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_HAVE_X86_64 */ - -#endif /* MBEDTLS_AESNI_H */ diff --git a/components/security/mbedtls/include/mbedtls/asn1.h b/components/security/mbedtls/include/mbedtls/asn1.h deleted file mode 100644 index 082832c8..00000000 --- a/components/security/mbedtls/include/mbedtls/asn1.h +++ /dev/null @@ -1,342 +0,0 @@ -/** - * \file asn1.h - * - * \brief Generic ASN.1 parsing - * - * 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) - */ -#ifndef MBEDTLS_ASN1_H -#define MBEDTLS_ASN1_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if defined(MBEDTLS_BIGNUM_C) -#include "bignum.h" -#endif - -/** - * \addtogroup asn1_module - * \{ - */ - -/** - * \name ASN1 Error codes - * These error codes are OR'ed to X509 error codes for - * higher error granularity. - * ASN1 is a standard to specify data structures. - * \{ - */ -#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ -#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ -#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ -#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ -#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ -#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ -#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ - -/* \} name */ - -/** - * \name DER constants - * These constants comply with DER encoded the ANS1 type tags. - * DER encoding uses hexadecimal representation. - * An example DER sequence is:\n - * - 0x02 -- tag indicating INTEGER - * - 0x01 -- length in octets - * - 0x05 -- value - * Such sequences are typically read into \c ::mbedtls_x509_buf. - * \{ - */ -#define MBEDTLS_ASN1_BOOLEAN 0x01 -#define MBEDTLS_ASN1_INTEGER 0x02 -#define MBEDTLS_ASN1_BIT_STRING 0x03 -#define MBEDTLS_ASN1_OCTET_STRING 0x04 -#define MBEDTLS_ASN1_NULL 0x05 -#define MBEDTLS_ASN1_OID 0x06 -#define MBEDTLS_ASN1_UTF8_STRING 0x0C -#define MBEDTLS_ASN1_SEQUENCE 0x10 -#define MBEDTLS_ASN1_SET 0x11 -#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 -#define MBEDTLS_ASN1_T61_STRING 0x14 -#define MBEDTLS_ASN1_IA5_STRING 0x16 -#define MBEDTLS_ASN1_UTC_TIME 0x17 -#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 -#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C -#define MBEDTLS_ASN1_BMP_STRING 0x1E -#define MBEDTLS_ASN1_PRIMITIVE 0x00 -#define MBEDTLS_ASN1_CONSTRUCTED 0x20 -#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 -/* \} name */ -/* \} addtogroup asn1_module */ - -/** Returns the size of the binary string, without the trailing \\0 */ -#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) - -/** - * Compares an mbedtls_asn1_buf structure to a reference OID. - * - * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a - * 'unsigned char *oid' here! - */ -#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ - ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ - memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name Functions to parse ASN.1 data structures - * \{ - */ - -/** - * Type-length-value structure that allows for ASN1 using DER. - */ -typedef struct mbedtls_asn1_buf -{ - int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ - size_t len; /**< ASN1 length, in octets. */ - unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ -} -mbedtls_asn1_buf; - -/** - * Container for ASN1 bit strings. - */ -typedef struct mbedtls_asn1_bitstring -{ - size_t len; /**< ASN1 length, in octets. */ - unsigned char unused_bits; /**< Number of unused bits at the end of the string */ - unsigned char *p; /**< Raw ASN1 data for the bit string */ -} -mbedtls_asn1_bitstring; - -/** - * Container for a sequence of ASN.1 items - */ -typedef struct mbedtls_asn1_sequence -{ - mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ - struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ -} -mbedtls_asn1_sequence; - -/** - * Container for a sequence or list of 'named' ASN.1 data items - */ -typedef struct mbedtls_asn1_named_data -{ - mbedtls_asn1_buf oid; /**< The object identifier. */ - mbedtls_asn1_buf val; /**< The named value. */ - struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ - unsigned char next_merged; /**< Merge next item into the current one? */ -} -mbedtls_asn1_named_data; - -/** - * \brief Get the length of an ASN.1 element. - * Updates the pointer to immediately behind the length. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param len The variable that will receive the value - * - * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching - * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is - * unparseable. - */ -int mbedtls_asn1_get_len( unsigned char **p, - const unsigned char *end, - size_t *len ); - -/** - * \brief Get the tag and length of the tag. Check for the requested tag. - * Updates the pointer to immediately behind the tag and length. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param len The variable that will receive the length - * \param tag The expected tag - * - * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did - * not match requested tag, or another specific ASN.1 error code. - */ -int mbedtls_asn1_get_tag( unsigned char **p, - const unsigned char *end, - size_t *len, int tag ); - -/** - * \brief Retrieve a boolean ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param val The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_bool( unsigned char **p, - const unsigned char *end, - int *val ); - -/** - * \brief Retrieve an integer ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param val The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_int( unsigned char **p, - const unsigned char *end, - int *val ); - -/** - * \brief Retrieve a bitstring ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param bs The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, - mbedtls_asn1_bitstring *bs); - -/** - * \brief Retrieve a bitstring ASN.1 tag without unused bits and its - * value. - * Updates the pointer to the beginning of the bit/octet string. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param len Length of the actual bit/octect string in bytes - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, - size_t *len ); - -/** - * \brief Parses and splits an ASN.1 "SEQUENCE OF " - * Updated the pointer to immediately behind the full sequence tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param cur First variable in the chain to fill - * \param tag Type of sequence - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_sequence_of( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_sequence *cur, - int tag); - -#if defined(MBEDTLS_BIGNUM_C) -/** - * \brief Retrieve a MPI value from an integer ASN.1 tag. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param X The MPI that will receive the value - * - * \return 0 if successful or a specific ASN.1 or MPI error code. - */ -int mbedtls_asn1_get_mpi( unsigned char **p, - const unsigned char *end, - mbedtls_mpi *X ); -#endif /* MBEDTLS_BIGNUM_C */ - -/** - * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. - * Updates the pointer to immediately behind the full - * AlgorithmIdentifier. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param alg The buffer to receive the OID - * \param params The buffer to receive the params (if any) - * - * \return 0 if successful or a specific ASN.1 or MPI error code. - */ -int mbedtls_asn1_get_alg( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); - -/** - * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no - * params. - * Updates the pointer to immediately behind the full - * AlgorithmIdentifier. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param alg The buffer to receive the OID - * - * \return 0 if successful or a specific ASN.1 or MPI error code. - */ -int mbedtls_asn1_get_alg_null( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg ); - -/** - * \brief Find a specific named_data entry in a sequence or list based on - * the OID. - * - * \param list The list to seek through - * \param oid The OID to look for - * \param len Size of the OID - * - * \return NULL if not found, or a pointer to the existing entry. - */ -mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, - const char *oid, size_t len ); - -/** - * \brief Free a mbedtls_asn1_named_data entry - * - * \param entry The named data entry to free - */ -void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); - -/** - * \brief Free all entries in a mbedtls_asn1_named_data list - * Head will be set to NULL - * - * \param head Pointer to the head of the list of named data entries to free - */ -void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); - -#ifdef __cplusplus -} -#endif - -#endif /* asn1.h */ diff --git a/components/security/mbedtls/include/mbedtls/asn1write.h b/components/security/mbedtls/include/mbedtls/asn1write.h deleted file mode 100644 index 73ff32b6..00000000 --- a/components/security/mbedtls/include/mbedtls/asn1write.h +++ /dev/null @@ -1,239 +0,0 @@ -/** - * \file asn1write.h - * - * \brief ASN.1 buffer writing functionality - * - * 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) - */ -#ifndef MBEDTLS_ASN1_WRITE_H -#define MBEDTLS_ASN1_WRITE_H - -#include "asn1.h" - -#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ - g += ret; } while( 0 ) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Write a length field in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param len the length to write - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); - -/** - * \brief Write a ASN.1 tag in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param tag the tag to write - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, - unsigned char tag ); - -/** - * \brief Write raw buffer data - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); - -#if defined(MBEDTLS_BIGNUM_C) -/** - * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param X the MPI to write - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); -#endif /* MBEDTLS_BIGNUM_C */ - -/** - * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); - -/** - * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param oid the OID to write - * \param oid_len length of the OID - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len ); - -/** - * \brief Write an AlgorithmIdentifier sequence in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param oid the OID of the algorithm - * \param oid_len length of the OID - * \param par_len length of parameters, which must be already written. - * If 0, NULL parameters are added - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - size_t par_len ); - -/** - * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param boolean 0 or 1 - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); - -/** - * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param val the integer value - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); - -/** - * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param text the text to write - * \param text_len length of the text - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ); - -/** - * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param text the text to write - * \param text_len length of the text - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ); - -/** - * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf the bitstring - * \param bits the total number of bits in the bitstring - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t bits ); - -/** - * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); - -/** - * \brief Create or find a specific named_data entry for writing in a - * sequence or list based on the OID. If not already in there, - * a new entry is added to the head of the list. - * Warning: Destructive behaviour for the val data! - * - * \param list Pointer to the location of the head of the list to seek - * through (will be updated in case of a new entry) - * \param oid The OID to look for - * \param oid_len Size of the OID - * \param val Data to store (can be NULL if you want to fill it by hand) - * \param val_len Minimum length of the data buffer needed - * - * \return NULL if if there was a memory allocation error, or a pointer - * to the new / existing entry. - */ -mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, - const char *oid, size_t oid_len, - const unsigned char *val, - size_t val_len ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/components/security/mbedtls/include/mbedtls/base64.h b/components/security/mbedtls/include/mbedtls/base64.h deleted file mode 100644 index 352c652d..00000000 --- a/components/security/mbedtls/include/mbedtls/base64.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * \file base64.h - * - * \brief RFC 1521 base64 encoding/decoding - * - * 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) - */ -#ifndef MBEDTLS_BASE64_H -#define MBEDTLS_BASE64_H - -#include - -#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ -#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Encode a buffer into base64 format - * - * \param dst destination buffer - * \param dlen size of the destination buffer - * \param olen number of bytes written - * \param src source buffer - * \param slen amount of data to be encoded - * - * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. - * *olen is always updated to reflect the amount - * of data that has (or would have) been written. - * If that length cannot be represented, then no data is - * written to the buffer and *olen is set to the maximum - * length representable as a size_t. - * - * \note Call this function with dlen = 0 to obtain the - * required buffer size in *olen - */ -int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ); - -/** - * \brief Decode a base64-formatted buffer - * - * \param dst destination buffer (can be NULL for checking size) - * \param dlen size of the destination buffer - * \param olen number of bytes written - * \param src source buffer - * \param slen amount of data to be decoded - * - * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or - * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is - * not correct. *olen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with *dst = NULL or dlen = 0 to obtain - * the required buffer size in *olen - */ -int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_base64_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* base64.h */ diff --git a/components/security/mbedtls/include/mbedtls/bignum.h b/components/security/mbedtls/include/mbedtls/bignum.h deleted file mode 100644 index aa51556a..00000000 --- a/components/security/mbedtls/include/mbedtls/bignum.h +++ /dev/null @@ -1,717 +0,0 @@ -/** - * \file bignum.h - * - * \brief Multi-precision integer library - * - * 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) - */ -#ifndef MBEDTLS_BIGNUM_H -#define MBEDTLS_BIGNUM_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ -#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ -#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ -#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ -#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ -#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ -#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ - -#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) - -/* - * Maximum size MPIs are allowed to grow to in number of limbs. - */ -#define MBEDTLS_MPI_MAX_LIMBS 10000 - -#if !defined(MBEDTLS_MPI_WINDOW_SIZE) -/* - * Maximum window size used for modular exponentiation. Default: 6 - * Minimum value: 1. Maximum value: 6. - * - * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used - * for the sliding window calculation. (So 64 by default) - * - * Reduction in size, reduces speed. - */ -#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ -#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ - -#if !defined(MBEDTLS_MPI_MAX_SIZE) -/* - * Maximum size of MPIs allowed in bits and bytes for user-MPIs. - * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) - * - * Note: Calculations can results temporarily in larger MPIs. So the number - * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. - */ -#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ -#endif /* !MBEDTLS_MPI_MAX_SIZE */ - -#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ - -/* - * When reading from files with mbedtls_mpi_read_file() and writing to files with - * mbedtls_mpi_write_file() the buffer should have space - * for a (short) label, the MPI (in the provided radix), the newline - * characters and the '\0'. - * - * By default we assume at least a 10 char label, a minimum radix of 10 - * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). - * Autosized at compile time for at least a 10 char label, a minimum radix - * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. - * - * This used to be statically sized to 1250 for a maximum of 4096 bit - * numbers (1234 decimal chars). - * - * Calculate using the formula: - * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + - * LabelSize + 6 - */ -#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) -#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 -#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) - -/* - * Define the base integer type, architecture-wise. - * - * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes) - * by defining MBEDTLS_HAVE_INT32 and undefining MBEDTLS_HAVE_ASM - */ -#if ( ! defined(MBEDTLS_HAVE_INT32) && \ - defined(_MSC_VER) && defined(_M_AMD64) ) - #define MBEDTLS_HAVE_INT64 - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; -#else - #if ( ! defined(MBEDTLS_HAVE_INT32) && \ - defined(__GNUC__) && ( \ - defined(__amd64__) || defined(__x86_64__) || \ - defined(__ppc64__) || defined(__powerpc64__) || \ - defined(__ia64__) || defined(__alpha__) || \ - (defined(__sparc__) && defined(__arch64__)) || \ - defined(__s390x__) || defined(__mips64) ) ) - #define MBEDTLS_HAVE_INT64 - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - /* mbedtls_t_udbl defined as 128-bit unsigned int */ - typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); - #define MBEDTLS_HAVE_UDBL - #else - #define MBEDTLS_HAVE_INT32 - typedef int32_t mbedtls_mpi_sint; - typedef uint32_t mbedtls_mpi_uint; - typedef uint64_t mbedtls_t_udbl; - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_HAVE_INT32 && __GNUC__ && 64-bit platform */ -#endif /* !MBEDTLS_HAVE_INT32 && _MSC_VER && _M_AMD64 */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MPI structure - */ -typedef struct -{ - int s; /*!< integer sign */ - size_t n; /*!< total # of limbs */ - mbedtls_mpi_uint *p; /*!< pointer to limbs */ -} -mbedtls_mpi; - -/** - * \brief Initialize one MPI (make internal references valid) - * This just makes it ready to be set or freed, - * but does not define a value for the MPI. - * - * \param X One MPI to initialize. - */ -void mbedtls_mpi_init( mbedtls_mpi *X ); - -/** - * \brief Unallocate one MPI - * - * \param X One MPI to unallocate. - */ -void mbedtls_mpi_free( mbedtls_mpi *X ); - -/** - * \brief Enlarge to the specified number of limbs - * - * \param X MPI to grow - * \param nblimbs The target number of limbs - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); - -/** - * \brief Resize down, keeping at least the specified number of limbs - * - * \param X MPI to shrink - * \param nblimbs The minimum number of limbs to keep - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); - -/** - * \brief Copy the contents of Y into X - * - * \param X Destination MPI - * \param Y Source MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Swap the contents of X and Y - * - * \param X First MPI value - * \param Y Second MPI value - */ -void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); - -/** - * \brief Safe conditional assignement X = Y if assign is 1 - * - * \param X MPI to conditionally assign to - * \param Y Value to be assigned - * \param assign 1: perform the assignment, 0: keep X's original value - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * - * \note This function is equivalent to - * if( assign ) mbedtls_mpi_copy( X, Y ); - * except that it avoids leaking any information about whether - * the assignment was done or not (the above code may leak - * information through branch prediction and/or memory access - * patterns analysis). - */ -int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); - -/** - * \brief Safe conditional swap X <-> Y if swap is 1 - * - * \param X First mbedtls_mpi value - * \param Y Second mbedtls_mpi value - * \param assign 1: perform the swap, 0: keep X and Y's original values - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * - * \note This function is equivalent to - * if( assign ) mbedtls_mpi_swap( X, Y ); - * except that it avoids leaking any information about whether - * the assignment was done or not (the above code may leak - * information through branch prediction and/or memory access - * patterns analysis). - */ -int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); - -/** - * \brief Set value from integer - * - * \param X MPI to set - * \param z Value to use - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); - -/** - * \brief Get a specific bit from X - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * - * \return Either a 0 or a 1 - */ -int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); - -/** - * \brief Set a bit of X to a specific value of 0 or 1 - * - * \note Will grow X if necessary to set a bit to 1 in a not yet - * existing limb. Will not grow if bit should be set to 0 - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * \param val The value to set the bit to (0 or 1) - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 - */ -int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); - -/** - * \brief Return the number of zero-bits before the least significant - * '1' bit - * - * Note: Thus also the zero-based index of the least significant '1' bit - * - * \param X MPI to use - */ -size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); - -/** - * \brief Return the number of bits up to and including the most - * significant '1' bit' - * - * Note: Thus also the one-based index of the most significant '1' bit - * - * \param X MPI to use - */ -size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); - -/** - * \brief Return the total size in bytes - * - * \param X MPI to use - */ -size_t mbedtls_mpi_size( const mbedtls_mpi *X ); - -/** - * \brief Import from an ASCII string - * - * \param X Destination MPI - * \param radix Input numeric base - * \param s Null-terminated string buffer - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - */ -int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); - -/** - * \brief Export into an ASCII string - * - * \param X Source MPI - * \param radix Output numeric base - * \param buf Buffer to write the string to - * \param buflen Length of buf - * \param olen Length of the string written, including final NUL byte - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. - * *olen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with buflen = 0 to obtain the - * minimum required buffer size in *olen. - */ -int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, - char *buf, size_t buflen, size_t *olen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Read X from an opened file - * - * \param X Destination MPI - * \param radix Input numeric base - * \param fin Input file handle - * - * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if - * the file read buffer is too small or a - * MBEDTLS_ERR_MPI_XXX error code - */ -int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); - -/** - * \brief Write X into an opened file, or stdout if fout is NULL - * - * \param p Prefix, can be NULL - * \param X Source MPI - * \param radix Output numeric base - * \param fout Output file handle (can be NULL) - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - * - * \note Set fout == NULL to print X on the console. - */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Import X from unsigned binary data, big endian - * - * \param X Destination MPI - * \param buf Input buffer - * \param buflen Input buffer size - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); - -/** - * \brief Export X into unsigned binary data, big endian. - * Always fills the whole buffer, which will start with zeros - * if the number is smaller. - * - * \param X Source MPI - * \param buf Output buffer - * \param buflen Output buffer size - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough - */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); - -/** - * \brief Left-shift: X <<= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); - -/** - * \brief Right-shift: X >>= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); - -/** - * \brief Compare unsigned values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if |X| is greater than |Y|, - * -1 if |X| is lesser than |Y| or - * 0 if |X| is equal to |Y| - */ -int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if X is greater than Y, - * -1 if X is lesser than Y or - * 0 if X is equal to Y - */ -int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param z The integer value to compare to - * - * \return 1 if X is greater than z, - * -1 if X is lesser than z or - * 0 if X is equal to z - */ -int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); - -/** - * \brief Unsigned addition: X = |A| + |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Unsigned subtraction: X = |A| - |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A - */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed addition: X = A + B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed subtraction: X = A - B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed addition: X = A + b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to add - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Signed subtraction: X = A - b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to subtract - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Baseline multiplication: X = A * B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Baseline multiplication: X = A * b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The unsigned integer value to multiply with - * - * \note b is unsigned - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); - -/** - * \brief Division by mbedtls_mpi: A = Q * B + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 - * - * \note Either Q or R can be NULL. - */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Division by int: A = Q * b + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 - * - * \note Either Q or R can be NULL. - */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Modulo: R = A mod B - * - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 - */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Modulo: r = A mod b - * - * \param r Destination mbedtls_mpi_uint - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 - */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Sliding-window exponentiation: X = A^E mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param E Exponent MPI - * \param N Modular MPI - * \param _RR Speed-up MPI used for recalculations - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or - * if E is negative - * - * \note _RR is used to avoid re-computing R*R mod N across - * multiple calls, which speeds up things a bit. It can - * be set to NULL if the extra performance is unneeded. - */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); - -/** - * \brief Fill an MPI X with size bytes of random - * - * \param X Destination MPI - * \param size Size in bytes - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Greatest common divisor: G = gcd(A, B) - * - * \param G Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Modular inverse: X = A^-1 mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param N Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or nil - MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N - */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); - -/** - * \brief Miller-Rabin primality test - * - * \param X MPI to check - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime - */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Prime number generation - * - * \param X Destination MPI - * \param nbits Required size of X in bits - * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) - * \param dh_flag If 1, then (X-1)/2 will be prime too - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 - */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_mpi_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* bignum.h */ diff --git a/components/security/mbedtls/include/mbedtls/bn_mul.h b/components/security/mbedtls/include/mbedtls/bn_mul.h deleted file mode 100644 index cac3f145..00000000 --- a/components/security/mbedtls/include/mbedtls/bn_mul.h +++ /dev/null @@ -1,885 +0,0 @@ -/** - * \file bn_mul.h - * - * \brief Multi-precision integer library - * - * 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) - */ -/* - * Multiply source vector [s] with b, add result - * to destination vector [d] and set carry c. - * - * Currently supports: - * - * . IA-32 (386+) . AMD64 / EM64T - * . IA-32 (SSE2) . Motorola 68000 - * . PowerPC, 32-bit . MicroBlaze - * . PowerPC, 64-bit . TriCore - * . SPARC v8 . ARM v3+ - * . Alpha . MIPS32 - * . C, longlong . C, generic - */ -#ifndef MBEDTLS_BN_MUL_H -#define MBEDTLS_BN_MUL_H - -#include "bignum.h" - -#if defined(MBEDTLS_HAVE_ASM) - -#ifndef asm -#define asm __asm -#endif - -/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ -#if defined(__GNUC__) && \ - ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) -#if defined(__i386__) - -#define MULADDC_INIT \ - asm( \ - "movl %%ebx, %0 \n\t" \ - "movl %5, %%esi \n\t" \ - "movl %6, %%edi \n\t" \ - "movl %7, %%ecx \n\t" \ - "movl %8, %%ebx \n\t" - -#define MULADDC_CORE \ - "lodsl \n\t" \ - "mull %%ebx \n\t" \ - "addl %%ecx, %%eax \n\t" \ - "adcl $0, %%edx \n\t" \ - "addl (%%edi), %%eax \n\t" \ - "adcl $0, %%edx \n\t" \ - "movl %%edx, %%ecx \n\t" \ - "stosl \n\t" - -#if defined(MBEDTLS_HAVE_SSE2) - -#define MULADDC_HUIT \ - "movd %%ecx, %%mm1 \n\t" \ - "movd %%ebx, %%mm0 \n\t" \ - "movd (%%edi), %%mm3 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd (%%esi), %%mm2 \n\t" \ - "pmuludq %%mm0, %%mm2 \n\t" \ - "movd 4(%%esi), %%mm4 \n\t" \ - "pmuludq %%mm0, %%mm4 \n\t" \ - "movd 8(%%esi), %%mm6 \n\t" \ - "pmuludq %%mm0, %%mm6 \n\t" \ - "movd 12(%%esi), %%mm7 \n\t" \ - "pmuludq %%mm0, %%mm7 \n\t" \ - "paddq %%mm2, %%mm1 \n\t" \ - "movd 4(%%edi), %%mm3 \n\t" \ - "paddq %%mm4, %%mm3 \n\t" \ - "movd 8(%%edi), %%mm5 \n\t" \ - "paddq %%mm6, %%mm5 \n\t" \ - "movd 12(%%edi), %%mm4 \n\t" \ - "paddq %%mm4, %%mm7 \n\t" \ - "movd %%mm1, (%%edi) \n\t" \ - "movd 16(%%esi), %%mm2 \n\t" \ - "pmuludq %%mm0, %%mm2 \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd 20(%%esi), %%mm4 \n\t" \ - "pmuludq %%mm0, %%mm4 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd 24(%%esi), %%mm6 \n\t" \ - "pmuludq %%mm0, %%mm6 \n\t" \ - "movd %%mm1, 4(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd 28(%%esi), %%mm3 \n\t" \ - "pmuludq %%mm0, %%mm3 \n\t" \ - "paddq %%mm5, %%mm1 \n\t" \ - "movd 16(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm2 \n\t" \ - "movd %%mm1, 8(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm7, %%mm1 \n\t" \ - "movd 20(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm4 \n\t" \ - "movd %%mm1, 12(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm2, %%mm1 \n\t" \ - "movd 24(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm6 \n\t" \ - "movd %%mm1, 16(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm4, %%mm1 \n\t" \ - "movd 28(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm3 \n\t" \ - "movd %%mm1, 20(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm6, %%mm1 \n\t" \ - "movd %%mm1, 24(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd %%mm1, 28(%%edi) \n\t" \ - "addl $32, %%edi \n\t" \ - "addl $32, %%esi \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd %%mm1, %%ecx \n\t" - -#define MULADDC_STOP \ - "emms \n\t" \ - "movl %4, %%ebx \n\t" \ - "movl %%ecx, %1 \n\t" \ - "movl %%edi, %2 \n\t" \ - "movl %%esi, %3 \n\t" \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); - -#else - -#define MULADDC_STOP \ - "movl %4, %%ebx \n\t" \ - "movl %%ecx, %1 \n\t" \ - "movl %%edi, %2 \n\t" \ - "movl %%esi, %3 \n\t" \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); -#endif /* SSE2 */ -#endif /* i386 */ - -#if defined(__amd64__) || defined (__x86_64__) - -#define MULADDC_INIT \ - asm( \ - "xorq %%r8, %%r8 \n\t" - -#define MULADDC_CORE \ - "movq (%%rsi), %%rax \n\t" \ - "mulq %%rbx \n\t" \ - "addq $8, %%rsi \n\t" \ - "addq %%rcx, %%rax \n\t" \ - "movq %%r8, %%rcx \n\t" \ - "adcq $0, %%rdx \n\t" \ - "nop \n\t" \ - "addq %%rax, (%%rdi) \n\t" \ - "adcq %%rdx, %%rcx \n\t" \ - "addq $8, %%rdi \n\t" - -#define MULADDC_STOP \ - : "+c" (c), "+D" (d), "+S" (s) \ - : "b" (b) \ - : "rax", "rdx", "r8" \ - ); - -#endif /* AMD64 */ - -#if defined(__mc68020__) || defined(__mcpu32__) - -#define MULADDC_INIT \ - asm( \ - "movl %3, %%a2 \n\t" \ - "movl %4, %%a3 \n\t" \ - "movl %5, %%d3 \n\t" \ - "movl %6, %%d2 \n\t" \ - "moveq #0, %%d0 \n\t" - -#define MULADDC_CORE \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "moveq #0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "addxl %%d4, %%d3 \n\t" - -#define MULADDC_STOP \ - "movl %%d3, %0 \n\t" \ - "movl %%a3, %1 \n\t" \ - "movl %%a2, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ - ); - -#define MULADDC_HUIT \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "addxl %%d0, %%d3 \n\t" - -#endif /* MC68000 */ - -#if defined(__powerpc64__) || defined(__ppc64__) - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( \ - "ld r3, %3 \n\t" \ - "ld r4, %4 \n\t" \ - "ld r5, %5 \n\t" \ - "ld r6, %6 \n\t" \ - "addi r3, r3, -8 \n\t" \ - "addi r4, r4, -8 \n\t" \ - "addic r5, r5, 0 \n\t" - -#define MULADDC_CORE \ - "ldu r7, 8(r3) \n\t" \ - "mulld r8, r7, r6 \n\t" \ - "mulhdu r9, r7, r6 \n\t" \ - "adde r8, r8, r5 \n\t" \ - "ld r7, 8(r4) \n\t" \ - "addze r5, r9 \n\t" \ - "addc r8, r8, r7 \n\t" \ - "stdu r8, 8(r4) \n\t" - -#define MULADDC_STOP \ - "addze r5, r5 \n\t" \ - "addi r4, r4, 8 \n\t" \ - "addi r3, r3, 8 \n\t" \ - "std r5, %0 \n\t" \ - "std r4, %1 \n\t" \ - "std r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - - -#else /* __MACH__ && __APPLE__ */ - -#define MULADDC_INIT \ - asm( \ - "ld %%r3, %3 \n\t" \ - "ld %%r4, %4 \n\t" \ - "ld %%r5, %5 \n\t" \ - "ld %%r6, %6 \n\t" \ - "addi %%r3, %%r3, -8 \n\t" \ - "addi %%r4, %%r4, -8 \n\t" \ - "addic %%r5, %%r5, 0 \n\t" - -#define MULADDC_CORE \ - "ldu %%r7, 8(%%r3) \n\t" \ - "mulld %%r8, %%r7, %%r6 \n\t" \ - "mulhdu %%r9, %%r7, %%r6 \n\t" \ - "adde %%r8, %%r8, %%r5 \n\t" \ - "ld %%r7, 8(%%r4) \n\t" \ - "addze %%r5, %%r9 \n\t" \ - "addc %%r8, %%r8, %%r7 \n\t" \ - "stdu %%r8, 8(%%r4) \n\t" - -#define MULADDC_STOP \ - "addze %%r5, %%r5 \n\t" \ - "addi %%r4, %%r4, 8 \n\t" \ - "addi %%r3, %%r3, 8 \n\t" \ - "std %%r5, %0 \n\t" \ - "std %%r4, %1 \n\t" \ - "std %%r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#endif /* __MACH__ && __APPLE__ */ - -#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( \ - "lwz r3, %3 \n\t" \ - "lwz r4, %4 \n\t" \ - "lwz r5, %5 \n\t" \ - "lwz r6, %6 \n\t" \ - "addi r3, r3, -4 \n\t" \ - "addi r4, r4, -4 \n\t" \ - "addic r5, r5, 0 \n\t" - -#define MULADDC_CORE \ - "lwzu r7, 4(r3) \n\t" \ - "mullw r8, r7, r6 \n\t" \ - "mulhwu r9, r7, r6 \n\t" \ - "adde r8, r8, r5 \n\t" \ - "lwz r7, 4(r4) \n\t" \ - "addze r5, r9 \n\t" \ - "addc r8, r8, r7 \n\t" \ - "stwu r8, 4(r4) \n\t" - -#define MULADDC_STOP \ - "addze r5, r5 \n\t" \ - "addi r4, r4, 4 \n\t" \ - "addi r3, r3, 4 \n\t" \ - "stw r5, %0 \n\t" \ - "stw r4, %1 \n\t" \ - "stw r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#else /* __MACH__ && __APPLE__ */ - -#define MULADDC_INIT \ - asm( \ - "lwz %%r3, %3 \n\t" \ - "lwz %%r4, %4 \n\t" \ - "lwz %%r5, %5 \n\t" \ - "lwz %%r6, %6 \n\t" \ - "addi %%r3, %%r3, -4 \n\t" \ - "addi %%r4, %%r4, -4 \n\t" \ - "addic %%r5, %%r5, 0 \n\t" - -#define MULADDC_CORE \ - "lwzu %%r7, 4(%%r3) \n\t" \ - "mullw %%r8, %%r7, %%r6 \n\t" \ - "mulhwu %%r9, %%r7, %%r6 \n\t" \ - "adde %%r8, %%r8, %%r5 \n\t" \ - "lwz %%r7, 4(%%r4) \n\t" \ - "addze %%r5, %%r9 \n\t" \ - "addc %%r8, %%r8, %%r7 \n\t" \ - "stwu %%r8, 4(%%r4) \n\t" - -#define MULADDC_STOP \ - "addze %%r5, %%r5 \n\t" \ - "addi %%r4, %%r4, 4 \n\t" \ - "addi %%r3, %%r3, 4 \n\t" \ - "stw %%r5, %0 \n\t" \ - "stw %%r4, %1 \n\t" \ - "stw %%r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#endif /* __MACH__ && __APPLE__ */ - -#endif /* PPC32 */ - -/* - * The Sparc(64) assembly is reported to be broken. - * Disable it for now, until we're able to fix it. - */ -#if 0 && defined(__sparc__) -#if defined(__sparc64__) - -#define MULADDC_INIT \ - asm( \ - "ldx %3, %%o0 \n\t" \ - "ldx %4, %%o1 \n\t" \ - "ld %5, %%o2 \n\t" \ - "ld %6, %%o3 \n\t" - -#define MULADDC_CORE \ - "ld [%%o0], %%o4 \n\t" \ - "inc 4, %%o0 \n\t" \ - "ld [%%o1], %%o5 \n\t" \ - "umul %%o3, %%o4, %%o4 \n\t" \ - "addcc %%o4, %%o2, %%o4 \n\t" \ - "rd %%y, %%g1 \n\t" \ - "addx %%g1, 0, %%g1 \n\t" \ - "addcc %%o4, %%o5, %%o4 \n\t" \ - "st %%o4, [%%o1] \n\t" \ - "addx %%g1, 0, %%o2 \n\t" \ - "inc 4, %%o1 \n\t" - - #define MULADDC_STOP \ - "st %%o2, %0 \n\t" \ - "stx %%o1, %1 \n\t" \ - "stx %%o0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "g1", "o0", "o1", "o2", "o3", "o4", \ - "o5" \ - ); - -#else /* __sparc64__ */ - -#define MULADDC_INIT \ - asm( \ - "ld %3, %%o0 \n\t" \ - "ld %4, %%o1 \n\t" \ - "ld %5, %%o2 \n\t" \ - "ld %6, %%o3 \n\t" - -#define MULADDC_CORE \ - "ld [%%o0], %%o4 \n\t" \ - "inc 4, %%o0 \n\t" \ - "ld [%%o1], %%o5 \n\t" \ - "umul %%o3, %%o4, %%o4 \n\t" \ - "addcc %%o4, %%o2, %%o4 \n\t" \ - "rd %%y, %%g1 \n\t" \ - "addx %%g1, 0, %%g1 \n\t" \ - "addcc %%o4, %%o5, %%o4 \n\t" \ - "st %%o4, [%%o1] \n\t" \ - "addx %%g1, 0, %%o2 \n\t" \ - "inc 4, %%o1 \n\t" - -#define MULADDC_STOP \ - "st %%o2, %0 \n\t" \ - "st %%o1, %1 \n\t" \ - "st %%o0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "g1", "o0", "o1", "o2", "o3", "o4", \ - "o5" \ - ); - -#endif /* __sparc64__ */ -#endif /* __sparc__ */ - -#if defined(__microblaze__) || defined(microblaze) - -#define MULADDC_INIT \ - asm( \ - "lwi r3, %3 \n\t" \ - "lwi r4, %4 \n\t" \ - "lwi r5, %5 \n\t" \ - "lwi r6, %6 \n\t" \ - "andi r7, r6, 0xffff \n\t" \ - "bsrli r6, r6, 16 \n\t" - -#define MULADDC_CORE \ - "lhui r8, r3, 0 \n\t" \ - "addi r3, r3, 2 \n\t" \ - "lhui r9, r3, 0 \n\t" \ - "addi r3, r3, 2 \n\t" \ - "mul r10, r9, r6 \n\t" \ - "mul r11, r8, r7 \n\t" \ - "mul r12, r9, r7 \n\t" \ - "mul r13, r8, r6 \n\t" \ - "bsrli r8, r10, 16 \n\t" \ - "bsrli r9, r11, 16 \n\t" \ - "add r13, r13, r8 \n\t" \ - "add r13, r13, r9 \n\t" \ - "bslli r10, r10, 16 \n\t" \ - "bslli r11, r11, 16 \n\t" \ - "add r12, r12, r10 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "add r12, r12, r11 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "lwi r10, r4, 0 \n\t" \ - "add r12, r12, r10 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "add r12, r12, r5 \n\t" \ - "addc r5, r13, r0 \n\t" \ - "swi r12, r4, 0 \n\t" \ - "addi r4, r4, 4 \n\t" - -#define MULADDC_STOP \ - "swi r5, %0 \n\t" \ - "swi r4, %1 \n\t" \ - "swi r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4" "r5", "r6", "r7", "r8", \ - "r9", "r10", "r11", "r12", "r13" \ - ); - -#endif /* MicroBlaze */ - -#if defined(__tricore__) - -#define MULADDC_INIT \ - asm( \ - "ld.a %%a2, %3 \n\t" \ - "ld.a %%a3, %4 \n\t" \ - "ld.w %%d4, %5 \n\t" \ - "ld.w %%d1, %6 \n\t" \ - "xor %%d5, %%d5 \n\t" - -#define MULADDC_CORE \ - "ld.w %%d0, [%%a2+] \n\t" \ - "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ - "ld.w %%d0, [%%a3] \n\t" \ - "addx %%d2, %%d2, %%d0 \n\t" \ - "addc %%d3, %%d3, 0 \n\t" \ - "mov %%d4, %%d3 \n\t" \ - "st.w [%%a3+], %%d2 \n\t" - -#define MULADDC_STOP \ - "st.w %0, %%d4 \n\t" \ - "st.a %1, %%a3 \n\t" \ - "st.a %2, %%a2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "d0", "d1", "e2", "d4", "a2", "a3" \ - ); - -#endif /* TriCore */ - -/* - * gcc -O0 by default uses r7 for the frame pointer, so it complains about our - * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, - * passing that option is not easy when building with yotta. - * - * On the other hand, -fomit-frame-pointer is implied by any -Ox options with - * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by - * clang and armcc5 under the same conditions). - * - * So, only use the optimized assembly below for optimized build, which avoids - * the build error and is pretty reasonable anyway. - */ -#if defined(__GNUC__) && !defined(__OPTIMIZE__) -#define MULADDC_CANNOT_USE_R7 -#endif - -#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) - -#if defined(__thumb__) && !defined(__thumb2__) - -#define MULADDC_INIT \ - asm( \ - "ldr r0, %3 \n\t" \ - "ldr r1, %4 \n\t" \ - "ldr r2, %5 \n\t" \ - "ldr r3, %6 \n\t" \ - "lsr r7, r3, #16 \n\t" \ - "mov r9, r7 \n\t" \ - "lsl r7, r3, #16 \n\t" \ - "lsr r7, r7, #16 \n\t" \ - "mov r8, r7 \n\t" - -#define MULADDC_CORE \ - "ldmia r0!, {r6} \n\t" \ - "lsr r7, r6, #16 \n\t" \ - "lsl r6, r6, #16 \n\t" \ - "lsr r6, r6, #16 \n\t" \ - "mov r4, r8 \n\t" \ - "mul r4, r6 \n\t" \ - "mov r3, r9 \n\t" \ - "mul r6, r3 \n\t" \ - "mov r5, r9 \n\t" \ - "mul r5, r7 \n\t" \ - "mov r3, r8 \n\t" \ - "mul r7, r3 \n\t" \ - "lsr r3, r6, #16 \n\t" \ - "add r5, r5, r3 \n\t" \ - "lsr r3, r7, #16 \n\t" \ - "add r5, r5, r3 \n\t" \ - "add r4, r4, r2 \n\t" \ - "mov r2, #0 \n\t" \ - "adc r5, r2 \n\t" \ - "lsl r3, r6, #16 \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r5, r2 \n\t" \ - "lsl r3, r7, #16 \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r5, r2 \n\t" \ - "ldr r3, [r1] \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r2, r5 \n\t" \ - "stmia r1!, {r4} \n\t" - -#define MULADDC_STOP \ - "str r2, %0 \n\t" \ - "str r1, %1 \n\t" \ - "str r0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "r8", "r9", "cc" \ - ); - -#else - -#define MULADDC_INIT \ - asm( \ - "ldr r0, %3 \n\t" \ - "ldr r1, %4 \n\t" \ - "ldr r2, %5 \n\t" \ - "ldr r3, %6 \n\t" - -#define MULADDC_CORE \ - "ldr r4, [r0], #4 \n\t" \ - "mov r5, #0 \n\t" \ - "ldr r6, [r1] \n\t" \ - "umlal r2, r5, r3, r4 \n\t" \ - "adds r7, r6, r2 \n\t" \ - "adc r2, r5, #0 \n\t" \ - "str r7, [r1], #4 \n\t" - -#define MULADDC_STOP \ - "str r2, %0 \n\t" \ - "str r1, %1 \n\t" \ - "str r0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "cc" \ - ); - -#endif /* Thumb */ - -#endif /* ARMv3 */ - -#if defined(__alpha__) - -#define MULADDC_INIT \ - asm( \ - "ldq $1, %3 \n\t" \ - "ldq $2, %4 \n\t" \ - "ldq $3, %5 \n\t" \ - "ldq $4, %6 \n\t" - -#define MULADDC_CORE \ - "ldq $6, 0($1) \n\t" \ - "addq $1, 8, $1 \n\t" \ - "mulq $6, $4, $7 \n\t" \ - "umulh $6, $4, $6 \n\t" \ - "addq $7, $3, $7 \n\t" \ - "cmpult $7, $3, $3 \n\t" \ - "ldq $5, 0($2) \n\t" \ - "addq $7, $5, $7 \n\t" \ - "cmpult $7, $5, $5 \n\t" \ - "stq $7, 0($2) \n\t" \ - "addq $2, 8, $2 \n\t" \ - "addq $6, $3, $3 \n\t" \ - "addq $5, $3, $3 \n\t" - -#define MULADDC_STOP \ - "stq $3, %0 \n\t" \ - "stq $2, %1 \n\t" \ - "stq $1, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ - ); -#endif /* Alpha */ - -#if defined(__mips__) && !defined(__mips64) - -#define MULADDC_INIT \ - asm( \ - "lw $10, %3 \n\t" \ - "lw $11, %4 \n\t" \ - "lw $12, %5 \n\t" \ - "lw $13, %6 \n\t" - -#define MULADDC_CORE \ - "lw $14, 0($10) \n\t" \ - "multu $13, $14 \n\t" \ - "addi $10, $10, 4 \n\t" \ - "mflo $14 \n\t" \ - "mfhi $9 \n\t" \ - "addu $14, $12, $14 \n\t" \ - "lw $15, 0($11) \n\t" \ - "sltu $12, $14, $12 \n\t" \ - "addu $15, $14, $15 \n\t" \ - "sltu $14, $15, $14 \n\t" \ - "addu $12, $12, $9 \n\t" \ - "sw $15, 0($11) \n\t" \ - "addu $12, $12, $14 \n\t" \ - "addi $11, $11, 4 \n\t" - -#define MULADDC_STOP \ - "sw $12, %0 \n\t" \ - "sw $11, %1 \n\t" \ - "sw $10, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ - ); - -#endif /* MIPS */ -#endif /* GNUC */ - -#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) - -#define MULADDC_INIT \ - __asm mov esi, s \ - __asm mov edi, d \ - __asm mov ecx, c \ - __asm mov ebx, b - -#define MULADDC_CORE \ - __asm lodsd \ - __asm mul ebx \ - __asm add eax, ecx \ - __asm adc edx, 0 \ - __asm add eax, [edi] \ - __asm adc edx, 0 \ - __asm mov ecx, edx \ - __asm stosd - -#if defined(MBEDTLS_HAVE_SSE2) - -#define EMIT __asm _emit - -#define MULADDC_HUIT \ - EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ - EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ - EMIT 0x0F EMIT 0x6E EMIT 0x1F \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x16 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ - EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ - EMIT 0x0F EMIT 0x7E EMIT 0x0F \ - EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ - EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ - EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x7E EMIT 0xC9 - -#define MULADDC_STOP \ - EMIT 0x0F EMIT 0x77 \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#else - -#define MULADDC_STOP \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#endif /* SSE2 */ -#endif /* MSVC */ - -#endif /* MBEDTLS_HAVE_ASM */ - -#if !defined(MULADDC_CORE) -#if defined(MBEDTLS_HAVE_UDBL) - -#define MULADDC_INIT \ -{ \ - mbedtls_t_udbl r; \ - mbedtls_mpi_uint r0, r1; - -#define MULADDC_CORE \ - r = *(s++) * (mbedtls_t_udbl) b; \ - r0 = (mbedtls_mpi_uint) r; \ - r1 = (mbedtls_mpi_uint)( r >> biL ); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#else -#define MULADDC_INIT \ -{ \ - mbedtls_mpi_uint s0, s1, b0, b1; \ - mbedtls_mpi_uint r0, r1, rx, ry; \ - b0 = ( b << biH ) >> biH; \ - b1 = ( b >> biH ); - -#define MULADDC_CORE \ - s0 = ( *s << biH ) >> biH; \ - s1 = ( *s >> biH ); s++; \ - rx = s0 * b1; r0 = s0 * b0; \ - ry = s1 * b0; r1 = s1 * b1; \ - r1 += ( rx >> biH ); \ - r1 += ( ry >> biH ); \ - rx <<= biH; ry <<= biH; \ - r0 += rx; r1 += (r0 < rx); \ - r0 += ry; r1 += (r0 < ry); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#endif /* C (generic) */ -#endif /* C (longlong) */ - -#endif /* bn_mul.h */ diff --git a/components/security/mbedtls/include/mbedtls/certs.h b/components/security/mbedtls/include/mbedtls/certs.h deleted file mode 100644 index ca49086e..00000000 --- a/components/security/mbedtls/include/mbedtls/certs.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * \file certs.h - * - * \brief Sample certificates and DHM parameters for testing - * - * 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) - */ -#ifndef MBEDTLS_CERTS_H -#define MBEDTLS_CERTS_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) -/* Concatenation of all CA certificates in PEM format if available */ -extern const char mbedtls_test_cas_pem[]; -extern const size_t mbedtls_test_cas_pem_len; -#endif - -/* List of all CA certificates, terminated by NULL */ -extern const char * mbedtls_test_cas[]; -extern const size_t mbedtls_test_cas_len[]; - -/* - * Convenience for users who just want a certificate: - * RSA by default, or ECDSA if RSA is not available - */ -extern const char * mbedtls_test_ca_crt; -extern const size_t mbedtls_test_ca_crt_len; -extern const char * mbedtls_test_ca_key; -extern const size_t mbedtls_test_ca_key_len; -extern const char * mbedtls_test_ca_pwd; -extern const size_t mbedtls_test_ca_pwd_len; -extern const char * mbedtls_test_srv_crt; -extern const size_t mbedtls_test_srv_crt_len; -extern const char * mbedtls_test_srv_key; -extern const size_t mbedtls_test_srv_key_len; -extern const char * mbedtls_test_cli_crt; -extern const size_t mbedtls_test_cli_crt_len; -extern const char * mbedtls_test_cli_key; -extern const size_t mbedtls_test_cli_key_len; - -#if defined(MBEDTLS_ECDSA_C) -extern const char mbedtls_test_ca_crt_ec[]; -extern const size_t mbedtls_test_ca_crt_ec_len; -extern const char mbedtls_test_ca_key_ec[]; -extern const size_t mbedtls_test_ca_key_ec_len; -extern const char mbedtls_test_ca_pwd_ec[]; -extern const size_t mbedtls_test_ca_pwd_ec_len; -extern const char mbedtls_test_srv_crt_ec[]; -extern const size_t mbedtls_test_srv_crt_ec_len; -extern const char mbedtls_test_srv_key_ec[]; -extern const size_t mbedtls_test_srv_key_ec_len; -extern const char mbedtls_test_cli_crt_ec[]; -extern const size_t mbedtls_test_cli_crt_ec_len; -extern const char mbedtls_test_cli_key_ec[]; -extern const size_t mbedtls_test_cli_key_ec_len; -#endif - -#if defined(MBEDTLS_RSA_C) -extern const char mbedtls_test_ca_crt_rsa[]; -extern const size_t mbedtls_test_ca_crt_rsa_len; -extern const char mbedtls_test_ca_key_rsa[]; -extern const size_t mbedtls_test_ca_key_rsa_len; -extern const char mbedtls_test_ca_pwd_rsa[]; -extern const size_t mbedtls_test_ca_pwd_rsa_len; -extern const char mbedtls_test_srv_crt_rsa[]; -extern const size_t mbedtls_test_srv_crt_rsa_len; -extern const char mbedtls_test_srv_key_rsa[]; -extern const size_t mbedtls_test_srv_key_rsa_len; -extern const char mbedtls_test_cli_crt_rsa[]; -extern const size_t mbedtls_test_cli_crt_rsa_len; -extern const char mbedtls_test_cli_key_rsa[]; -extern const size_t mbedtls_test_cli_key_rsa_len; -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* certs.h */ diff --git a/components/security/mbedtls/include/mbedtls/check_config.h b/components/security/mbedtls/include/mbedtls/check_config.h deleted file mode 100644 index 086851c8..00000000 --- a/components/security/mbedtls/include/mbedtls/check_config.h +++ /dev/null @@ -1,675 +0,0 @@ -/** - * \file check_config.h - * - * \brief Consistency checks for configuration options - * - * Copyright (C) 2006-2016, 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) - */ - -/* - * It is recommended to include this file from your config.h - * in order to catch dependency issues early. - */ - -#ifndef MBEDTLS_CHECK_CONFIG_H -#define MBEDTLS_CHECK_CONFIG_H - -/* - * We assume CHAR_BIT is 8 in many places. In practice, this is true on our - * target platforms, so not an issue, but let's just be extra sure. - */ -#include -#if CHAR_BIT != 8 -#error "mbed TLS requires a platform with 8-bit chars" -#endif - -#if defined(_WIN32) -#if !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_C is required on Windows" -#endif - -/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as - * it would confuse config.pl. */ -#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ - !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) -#define MBEDTLS_PLATFORM_SNPRINTF_ALT -#endif -#endif /* _WIN32 */ - -#if defined(TARGET_LIKE_MBED) && \ - ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) -#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" -#endif - -#if defined(MBEDTLS_DEPRECATED_WARNING) && \ - !defined(__GNUC__) && !defined(__clang__) -#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" -#endif - -#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) -#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" -#endif - -#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_AESNI_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) -#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) -#error "MBEDTLS_DHM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CMAC_C) && \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) -#error "MBEDTLS_CMAC_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) -#error "MBEDTLS_ECDH_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECDSA_C) && \ - ( !defined(MBEDTLS_ECP_C) || \ - !defined(MBEDTLS_ASN1_PARSE_C) || \ - !defined(MBEDTLS_ASN1_WRITE_C) ) -#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECJPAKE_C) && \ - ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) -#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) -#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ - !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) -#error "MBEDTLS_ECP_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ - !defined(MBEDTLS_SHA256_C)) -#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" -#endif -#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ - defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) -#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" -#endif -#if defined(MBEDTLS_ENTROPY_C) && \ - ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ - && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) -#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" -#endif -#if defined(MBEDTLS_ENTROPY_C) && \ - defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) -#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ - ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) -#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" -#endif -#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ - ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ - defined(MBEDTLS_HAVEGE_C) ) -#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" -#endif - -#if defined(MBEDTLS_GCM_C) && ( \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) -#error "MBEDTLS_GCM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) -#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) -#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) -#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) -#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) -#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ - !defined(MBEDTLS_ECDH_C) -#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C) ) -#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ - ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ - !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ - !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ - ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ - !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) -#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ - ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) -#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) -#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) -#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_C) && \ - ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) -#error "MBEDTLS_PK_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ - defined(MBEDTLS_PLATFORM_EXIT_ALT) ) -#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ - ( !defined(MBEDTLS_PLATFORM_C) ||\ - !defined(MBEDTLS_HAVE_TIME) ) -#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ - ( !defined(MBEDTLS_PLATFORM_C) ||\ - !defined(MBEDTLS_HAVE_TIME) ) -#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ - ( !defined(MBEDTLS_PLATFORM_C) ||\ - !defined(MBEDTLS_HAVE_TIME) ) -#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ - defined(MBEDTLS_PLATFORM_TIME_ALT) ) -#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ - defined(MBEDTLS_PLATFORM_TIME_ALT) ) -#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ - defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) -#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ - ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) -#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ - defined(MBEDTLS_PLATFORM_STD_FREE) -#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) -#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ - ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) -#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ - defined(MBEDTLS_PLATFORM_STD_CALLOC) -#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) -#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" -#endif - -#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ - defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) -#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ - defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) -#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ - !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) -#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) -#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) -#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) -#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ - !defined(MBEDTLS_PLATFORM_EXIT_ALT) -#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ - ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ - !defined(MBEDTLS_HAVE_TIME) ) -#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ - !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ - !defined(MBEDTLS_PLATFORM_PRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ - !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ - ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) -#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ - !defined(MBEDTLS_ENTROPY_NV_SEED) -#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ - !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ - !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ - defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) -#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ - defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) -#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_RSA_C) && ( \ - ( !defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_PK_ALT) ) || \ - ( !defined(MBEDTLS_OID_C) && !defined(MBEDTLS_IOT_SPECIFIC) ) ) -#error "MBEDTLS_RSA_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ - !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" -#endif - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ - ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) -#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ - !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) -#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ - !defined(MBEDTLS_MD_C) ) -#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) -#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2)) -#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1))) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) -#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ - !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) -#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ - ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) -#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ - ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) -#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" -#endif - -#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) -#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ - !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) -#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ - !defined(MBEDTLS_X509_CRT_PARSE_C) -#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_THREADING_PTHREAD) -#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" -#endif -#define MBEDTLS_THREADING_IMPL -#endif - -#if defined(MBEDTLS_THREADING_ALT) -#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" -#endif -#define MBEDTLS_THREADING_IMPL -#endif - -#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_C defined, single threading implementation required" -#endif -#undef MBEDTLS_THREADING_IMPL - -#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) -#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_USE_C) && ( \ - ( !defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_PK_ALT)) || \ - (!defined(MBEDTLS_OID_C) && !defined(MBEDTLS_IOT_SPECIFIC)) || \ - !defined(MBEDTLS_ASN1_PARSE_C) || !defined(MBEDTLS_PK_PARSE_C) ) -#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ - !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ - !defined(MBEDTLS_PK_WRITE_C) ) -#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) -#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) -#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) -#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) -#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) -#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" -#endif -#if defined MBEDTLS_THREADING_C -#if !defined(MBEDTLS_THREADING_PTHREAD) && !defined(MBEDTLS_THREADING_ALT) -#error "MBEDTLS_THREADING_C defined, but no threads are active" -#endif -#endif - -#if defined(MBEDTLS_THREADING_PTHREAD) && defined(MBEDTLS_THREADING_ALT) -#error "MBEDTLS_THREADING_PTHREAD and MBEDTLS_THREADING_ALT can not be defined simultaneously" -#endif - -#if defined(MBEDTLS_PK_ALT) -#undef MBEDTLS_BIGNUM_C -#endif - -/* - * Avoid warning from -pedantic. This is a convenient place for this - * workaround since this is included by every single file before the - * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. - */ -typedef int mbedtls_iso_c_forbids_empty_translation_units; - -#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/components/security/mbedtls/include/mbedtls/cipher.h b/components/security/mbedtls/include/mbedtls/cipher.h deleted file mode 100644 index b12e3884..00000000 --- a/components/security/mbedtls/include/mbedtls/cipher.h +++ /dev/null @@ -1,709 +0,0 @@ -/** - * \file cipher.h - * - * \brief Generic cipher wrapper. - * - * \author Adriaan de Jong - * - * 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) - */ - -#ifndef MBEDTLS_CIPHER_H -#define MBEDTLS_CIPHER_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) -#define MBEDTLS_CIPHER_MODE_AEAD -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#define MBEDTLS_CIPHER_MODE_WITH_PADDING -#endif - -#if defined(MBEDTLS_ARC4_C) -#define MBEDTLS_CIPHER_MODE_STREAM -#endif - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ -#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ -#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ -#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ -#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ -#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid, eg because it was free()ed. */ - -#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */ -#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - MBEDTLS_CIPHER_ID_NONE = 0, - MBEDTLS_CIPHER_ID_NULL, - MBEDTLS_CIPHER_ID_AES, - MBEDTLS_CIPHER_ID_DES, - MBEDTLS_CIPHER_ID_3DES, - MBEDTLS_CIPHER_ID_CAMELLIA, - MBEDTLS_CIPHER_ID_BLOWFISH, - MBEDTLS_CIPHER_ID_ARC4, -} mbedtls_cipher_id_t; - -typedef enum { - MBEDTLS_CIPHER_NONE = 0, - MBEDTLS_CIPHER_NULL, - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_CIPHER_AES_128_CBC, - MBEDTLS_CIPHER_AES_192_CBC, - MBEDTLS_CIPHER_AES_256_CBC, - MBEDTLS_CIPHER_AES_128_CFB128, - MBEDTLS_CIPHER_AES_192_CFB128, - MBEDTLS_CIPHER_AES_256_CFB128, - MBEDTLS_CIPHER_AES_128_CTR, - MBEDTLS_CIPHER_AES_192_CTR, - MBEDTLS_CIPHER_AES_256_CTR, - MBEDTLS_CIPHER_AES_128_GCM, - MBEDTLS_CIPHER_AES_192_GCM, - MBEDTLS_CIPHER_AES_256_GCM, - MBEDTLS_CIPHER_CAMELLIA_128_ECB, - MBEDTLS_CIPHER_CAMELLIA_192_ECB, - MBEDTLS_CIPHER_CAMELLIA_256_ECB, - MBEDTLS_CIPHER_CAMELLIA_128_CBC, - MBEDTLS_CIPHER_CAMELLIA_192_CBC, - MBEDTLS_CIPHER_CAMELLIA_256_CBC, - MBEDTLS_CIPHER_CAMELLIA_128_CFB128, - MBEDTLS_CIPHER_CAMELLIA_192_CFB128, - MBEDTLS_CIPHER_CAMELLIA_256_CFB128, - MBEDTLS_CIPHER_CAMELLIA_128_CTR, - MBEDTLS_CIPHER_CAMELLIA_192_CTR, - MBEDTLS_CIPHER_CAMELLIA_256_CTR, - MBEDTLS_CIPHER_CAMELLIA_128_GCM, - MBEDTLS_CIPHER_CAMELLIA_192_GCM, - MBEDTLS_CIPHER_CAMELLIA_256_GCM, - MBEDTLS_CIPHER_DES_ECB, - MBEDTLS_CIPHER_DES_CBC, - MBEDTLS_CIPHER_DES_EDE_ECB, - MBEDTLS_CIPHER_DES_EDE_CBC, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_CIPHER_DES_EDE3_CBC, - MBEDTLS_CIPHER_BLOWFISH_ECB, - MBEDTLS_CIPHER_BLOWFISH_CBC, - MBEDTLS_CIPHER_BLOWFISH_CFB64, - MBEDTLS_CIPHER_BLOWFISH_CTR, - MBEDTLS_CIPHER_ARC4_128, - MBEDTLS_CIPHER_AES_128_CCM, - MBEDTLS_CIPHER_AES_192_CCM, - MBEDTLS_CIPHER_AES_256_CCM, - MBEDTLS_CIPHER_CAMELLIA_128_CCM, - MBEDTLS_CIPHER_CAMELLIA_192_CCM, - MBEDTLS_CIPHER_CAMELLIA_256_CCM, -} mbedtls_cipher_type_t; - -typedef enum { - MBEDTLS_MODE_NONE = 0, - MBEDTLS_MODE_ECB, - MBEDTLS_MODE_CBC, - MBEDTLS_MODE_CFB, - MBEDTLS_MODE_OFB, /* Unused! */ - MBEDTLS_MODE_CTR, - MBEDTLS_MODE_GCM, - MBEDTLS_MODE_STREAM, - MBEDTLS_MODE_CCM, -} mbedtls_cipher_mode_t; - -typedef enum { - MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default) */ - MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding */ - MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding */ - MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible!) */ - MBEDTLS_PADDING_NONE, /**< never pad (full blocks only) */ -} mbedtls_cipher_padding_t; - -typedef enum { - MBEDTLS_OPERATION_NONE = -1, - MBEDTLS_DECRYPT = 0, - MBEDTLS_ENCRYPT, -} mbedtls_operation_t; - -enum { - /** Undefined key length */ - MBEDTLS_KEY_LENGTH_NONE = 0, - /** Key length, in bits (including parity), for DES keys */ - MBEDTLS_KEY_LENGTH_DES = 64, - /** Key length, in bits (including parity), for DES in two key EDE */ - MBEDTLS_KEY_LENGTH_DES_EDE = 128, - /** Key length, in bits (including parity), for DES in three-key EDE */ - MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, -}; - -/** Maximum length of any IV, in bytes */ -#define MBEDTLS_MAX_IV_LENGTH 16 -/** Maximum block size of any cipher, in bytes */ -#define MBEDTLS_MAX_BLOCK_LENGTH 16 - -/** - * Base cipher information (opaque struct). - */ -typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; - -/** - * CMAC context (opaque struct). - */ -typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; - -/** - * Cipher information. Allows cipher functions to be called in a generic way. - */ -typedef struct { - /** Full cipher identifier (e.g. MBEDTLS_CIPHER_AES_256_CBC) */ - mbedtls_cipher_type_t type; - - /** Cipher mode (e.g. MBEDTLS_MODE_CBC) */ - mbedtls_cipher_mode_t mode; - - /** Cipher key length, in bits (default length for variable sized ciphers) - * (Includes parity bits for ciphers like DES) */ - unsigned int key_bitlen; - - /** Name of the cipher */ - const char * name; - - /** IV/NONCE size, in bytes. - * For cipher that accept many sizes: recommended size */ - unsigned int iv_size; - - /** Flags for variable IV size, variable key size, etc. */ - int flags; - - /** block size, in bytes */ - unsigned int block_size; - - /** Base cipher information and functions */ - const mbedtls_cipher_base_t *base; - -} mbedtls_cipher_info_t; - -/** - * Generic cipher context. - */ -typedef struct { - /** Information about the associated cipher */ - const mbedtls_cipher_info_t *cipher_info; - - /** Key length to use */ - int key_bitlen; - - /** Operation that the context's key has been initialised for */ - mbedtls_operation_t operation; - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /** Padding functions to use, if relevant for cipher mode */ - void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); - int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); -#endif - - /** Buffer for data that hasn't been encrypted yet */ - unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; - - /** Number of bytes that still need processing */ - size_t unprocessed_len; - - /** Current IV or NONCE_COUNTER for CTR-mode */ - unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; - - /** IV size in bytes (for ciphers with variable-length IVs) */ - size_t iv_size; - - /** Cipher-specific context */ - void *cipher_ctx; - -#if defined(MBEDTLS_CMAC_C) - /** CMAC Specific context */ - mbedtls_cmac_context_t *cmac_ctx; -#endif -} mbedtls_cipher_context_t; - -/** - * \brief Returns the list of ciphers supported by the generic cipher module. - * - * \return a statically allocated array of ciphers, the last entry - * is 0. - */ -const int *mbedtls_cipher_list( void ); - -/** - * \brief Returns the cipher information structure associated - * with the given cipher name. - * - * \param cipher_name Name of the cipher to search for. - * - * \return the cipher information structure associated with the - * given cipher_name, or NULL if not found. - */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); - -/** - * \brief Returns the cipher information structure associated - * with the given cipher type. - * - * \param cipher_type Type of the cipher to search for. - * - * \return the cipher information structure associated with the - * given cipher_type, or NULL if not found. - */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); - -/** - * \brief Returns the cipher information structure associated - * with the given cipher id, key size and mode. - * - * \param cipher_id Id of the cipher to search for - * (e.g. MBEDTLS_CIPHER_ID_AES) - * \param key_bitlen Length of the key in bits - * \param mode Cipher mode (e.g. MBEDTLS_MODE_CBC) - * - * \return the cipher information structure associated with the - * given cipher_type, or NULL if not found. - */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, - int key_bitlen, - const mbedtls_cipher_mode_t mode ); - -/** - * \brief Initialize a cipher_context (as NONE) - */ -void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); - -/** - * \brief Free and clear the cipher-specific context of ctx. - * Freeing ctx itself remains the responsibility of the - * caller. - */ -void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); - -/** - * \brief Initialises and fills the cipher context structure with - * the appropriate values. - * - * \note Currently also clears structure. In future versions you - * will be required to call mbedtls_cipher_init() on the structure - * first. - * - * \param ctx context to initialise. May not be NULL. - * \param cipher_info cipher to use. - * - * \return 0 on success, - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, - * MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the - * cipher-specific context failed. - */ -int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); - -/** - * \brief Returns the block size of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return size of the cipher's blocks, or 0 if ctx has not been - * initialised. - */ -static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - return ctx->cipher_info->block_size; -} - -/** - * \brief Returns the mode of operation for the cipher. - * (e.g. MBEDTLS_MODE_CBC) - * - * \param ctx cipher's context. Must have been initialised. - * - * \return mode of operation, or MBEDTLS_MODE_NONE if ctx - * has not been initialised. - */ -static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return MBEDTLS_MODE_NONE; - - return ctx->cipher_info->mode; -} - -/** - * \brief Returns the size of the cipher's IV/NONCE in bytes. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return If IV has not been set yet: (recommended) IV size - * (0 for ciphers not using IV/NONCE). - * If IV has already been set: actual size. - */ -static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - if( ctx->iv_size != 0 ) - return (int) ctx->iv_size; - - return (int) ctx->cipher_info->iv_size; -} - -/** - * \brief Returns the type of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return type of the cipher, or MBEDTLS_CIPHER_NONE if ctx has - * not been initialised. - */ -static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return MBEDTLS_CIPHER_NONE; - - return ctx->cipher_info->type; -} - -/** - * \brief Returns the name of the given cipher, as a string. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return name of the cipher, or NULL if ctx was not initialised. - */ -static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - return ctx->cipher_info->name; -} - -/** - * \brief Returns the key length of the cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return cipher's key length, in bits, or - * MBEDTLS_KEY_LENGTH_NONE if ctx has not been - * initialised. - */ -static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return MBEDTLS_KEY_LENGTH_NONE; - - return (int) ctx->cipher_info->key_bitlen; -} - -/** - * \brief Returns the operation of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return operation (MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT), - * or MBEDTLS_OPERATION_NONE if ctx has not been - * initialised. - */ -static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return MBEDTLS_OPERATION_NONE; - - return ctx->operation; -} - -/** - * \brief Set the key to use with the given context. - * - * \param ctx generic cipher context. May not be NULL. Must have been - * initialised using cipher_context_from_type or - * cipher_context_from_string. - * \param key The key to use. - * \param key_bitlen key length to use, in bits. - * \param operation Operation that the key will be used for, either - * MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT. - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails or a cipher specific - * error code. - */ -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ); - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) -/** - * \brief Set padding mode, for cipher modes that use padding. - * (Default: PKCS7 padding.) - * - * \param ctx generic cipher context - * \param mode padding mode - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE - * if selected padding mode is not supported, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode - * does not support padding. - */ -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - -/** - * \brief Set the initialization vector (IV) or nonce - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * - * \returns 0 on success, or MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA - * - * \note Some ciphers don't use IVs nor NONCE. For these - * ciphers, this function has no effect. - */ -int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ); - -/** - * \brief Finish preparation of the given context - * - * \param ctx generic cipher context - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA - * if parameter verification fails. - */ -int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); - -#if defined(MBEDTLS_GCM_C) -/** - * \brief Add additional data (for AEAD ciphers). - * Currently only supported with GCM. - * Must be called exactly once, after mbedtls_cipher_reset(). - * - * \param ctx generic cipher context - * \param ad Additional data to use. - * \param ad_len Length of ad. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, - const unsigned char *ad, size_t ad_len ); -#endif /* MBEDTLS_GCM_C */ - -/** - * \brief Generic cipher update function. Encrypts/decrypts - * using the given cipher context. Writes as many block - * size'd blocks of data as possible to output. Any data - * that cannot be written immediately will either be added - * to the next block, or flushed when cipher_final is - * called. - * Exception: for MBEDTLS_MODE_ECB, expects single block - * in size (e.g. 16 bytes for AES) - * - * \param ctx generic cipher context - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. Should be able to hold at - * least ilen + block_size. Cannot be the same buffer as - * input! - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an - * unsupported mode for a cipher or a cipher specific - * error code. - * - * \note If the underlying cipher is GCM, all calls to this - * function, except the last one before mbedtls_cipher_finish(), - * must have ilen a multiple of the block size. - */ -int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen ); - -/** - * \brief Generic cipher finalisation function. If data still - * needs to be flushed from an incomplete block, data - * contained within it will be padded with the size of - * the last block, and written to the output buffer. - * - * \param ctx Generic cipher context - * \param output buffer to write data to. Needs block_size available. - * \param olen length of the data written to the output buffer. - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, - * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting or a cipher specific error code. - */ -int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output, size_t *olen ); - -#if defined(MBEDTLS_GCM_C) -/** - * \brief Write tag for AEAD ciphers. - * Currently only supported with GCM. - * Must be called after mbedtls_cipher_finish(). - * - * \param ctx Generic cipher context - * \param tag buffer to write the tag - * \param tag_len Length of the tag to write - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, - unsigned char *tag, size_t tag_len ); - -/** - * \brief Check tag for AEAD ciphers. - * Currently only supported with GCM. - * Must be called after mbedtls_cipher_finish(). - * - * \param ctx Generic cipher context - * \param tag Buffer holding the tag - * \param tag_len Length of the tag to check - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, - const unsigned char *tag, size_t tag_len ); -#endif /* MBEDTLS_GCM_C */ - -/** - * \brief Generic all-in-one encryption/decryption - * (for all ciphers except AEAD constructs). - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. Should be able to hold at - * least ilen + block_size. Cannot be the same buffer as - * input! - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * - * \note Some ciphers don't use IVs nor NONCE. For these - * ciphers, use iv = NULL and iv_len = 0. - * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, or - * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting, or - * a cipher specific error code. - */ -int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen ); - -#if defined(MBEDTLS_CIPHER_MODE_AEAD) -/** - * \brief Generic autenticated encryption (AEAD ciphers). - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param ad Additional data to authenticate. - * \param ad_len Length of ad. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. - * Should be able to hold at least ilen. - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * \param tag buffer for the authentication tag - * \param tag_len desired tag length - * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * a cipher specific error code. - */ -int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len ); - -/** - * \brief Generic autenticated decryption (AEAD ciphers). - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param ad Additional data to be authenticated. - * \param ad_len Length of ad. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. - * Should be able to hold at least ilen. - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * \param tag buffer holding the authentication tag - * \param tag_len length of the authentication tag - * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * MBEDTLS_ERR_CIPHER_AUTH_FAILED if data isn't authentic, - * or a cipher specific error code. - * - * \note If the data is not authentic, then the output buffer - * is zeroed out to prevent the unauthentic plaintext to - * be used by mistake, making this interface safer. - */ -int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - const unsigned char *tag, size_t tag_len ); -#endif /* MBEDTLS_CIPHER_MODE_AEAD */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_CIPHER_H */ diff --git a/components/security/mbedtls/include/mbedtls/cipher_internal.h b/components/security/mbedtls/include/mbedtls/cipher_internal.h deleted file mode 100644 index 6c58bcc5..00000000 --- a/components/security/mbedtls/include/mbedtls/cipher_internal.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * \file cipher_internal.h - * - * \brief Cipher wrappers. - * - * \author Adriaan de Jong - * - * 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) - */ -#ifndef MBEDTLS_CIPHER_WRAP_H -#define MBEDTLS_CIPHER_WRAP_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "cipher.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Base cipher information. The non-mode specific functions and values. - */ -struct mbedtls_cipher_base_t -{ - /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ - mbedtls_cipher_id_t cipher; - - /** Encrypt using ECB */ - int (*ecb_func)( void *ctx, mbedtls_operation_t mode, - const unsigned char *input, unsigned char *output ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - /** Encrypt using CBC */ - int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, - unsigned char *iv, const unsigned char *input, - unsigned char *output ); -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CFB) - /** Encrypt using CFB (Full length) */ - int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, - unsigned char *iv, const unsigned char *input, - unsigned char *output ); -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CTR) - /** Encrypt using CTR */ - int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ); -#endif - -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - /** Encrypt using STREAM */ - int (*stream_func)( void *ctx, size_t length, - const unsigned char *input, unsigned char *output ); -#endif - - /** Set key for encryption purposes */ - int (*setkey_enc_func)( void *ctx, const unsigned char *key, - unsigned int key_bitlen ); - - /** Set key for decryption purposes */ - int (*setkey_dec_func)( void *ctx, const unsigned char *key, - unsigned int key_bitlen); - - /** Allocate a new context */ - void * (*ctx_alloc_func)( void ); - - /** Free the given context */ - void (*ctx_free_func)( void *ctx ); - -}; - -typedef struct -{ - mbedtls_cipher_type_t type; - const mbedtls_cipher_info_t *info; -} mbedtls_cipher_definition_t; - -extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; - -extern int mbedtls_cipher_supported[]; - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/components/security/mbedtls/include/mbedtls/cmac.h b/components/security/mbedtls/include/mbedtls/cmac.h deleted file mode 100644 index 9a2b96bc..00000000 --- a/components/security/mbedtls/include/mbedtls/cmac.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * \file cmac.h - * - * \brief Cipher-based Message Authentication Code (CMAC) Mode for - * Authentication - * - * Copyright (C) 2015-2016, 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) - */ -#ifndef MBEDTLS_CMAC_H -#define MBEDTLS_CMAC_H - -#include "mbedtls/cipher.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MBEDTLS_AES_BLOCK_SIZE 16 -#define MBEDTLS_DES3_BLOCK_SIZE 8 - -#if defined(MBEDTLS_AES_C) -#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /* longest used by CMAC is AES */ -#else -#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */ -#endif - -/** - * CMAC context structure - Contains internal state information only - */ -struct mbedtls_cmac_context_t -{ - /** Internal state of the CMAC algorithm */ - unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; - - /** Unprocessed data - either data that was not block aligned and is still - * pending to be processed, or the final block */ - unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; - - /** Length of data pending to be processed */ - size_t unprocessed_len; -}; - -/** - * \brief Set the CMAC key and prepare to authenticate the input - * data. - * Should be called with an initialized cipher context. - * - * \param ctx Cipher context. This should be a cipher context, - * initialized to be one of the following types: - * MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_CIPHER_AES_192_ECB, - * MBEDTLS_CIPHER_AES_256_ECB or - * MBEDTLS_CIPHER_DES_EDE3_ECB. - * \param key CMAC key - * \param keybits length of the CMAC key in bits - * (must be acceptable by the cipher) - * - * \return 0 if successful, or a cipher specific error code - */ -int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, - const unsigned char *key, size_t keybits ); - -/** - * \brief Generic CMAC process buffer. - * Called between mbedtls_cipher_cmac_starts() or - * mbedtls_cipher_cmac_reset() and - * mbedtls_cipher_cmac_finish(). - * May be called repeatedly. - * - * \param ctx CMAC context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, - const unsigned char *input, size_t ilen ); - -/** - * \brief Output CMAC. - * Called after mbedtls_cipher_cmac_update(). - * Usually followed by mbedtls_cipher_cmac_reset(), then - * mbedtls_cipher_cmac_starts(), or mbedtls_cipher_free(). - * - * \param ctx CMAC context - * \param output Generic CMAC checksum result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output ); - -/** - * \brief Prepare to authenticate a new message with the same key. - * Called after mbedtls_cipher_cmac_finish() and before - * mbedtls_cipher_cmac_update(). - * - * \param ctx CMAC context to be reset - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); - -/** - * \brief Output = Generic_CMAC( cmac key, input buffer ) - * - * \param cipher_info message digest info - * \param key CMAC key - * \param keylen length of the CMAC key in bits - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic CMAC-result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, - const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ); - -#if defined(MBEDTLS_AES_C) -/** - * \brief AES-CMAC-128-PRF - * Implementation of (AES-CMAC-PRF-128), as defined in RFC 4615 - * - * \param key PRF key - * \param key_len PRF key length in bytes - * \param input buffer holding the input data - * \param in_len length of the input data in bytes - * \param output buffer holding the generated pseudorandom output (16 bytes) - * - * \return 0 if successful - */ -int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, - const unsigned char *input, size_t in_len, - unsigned char output[16] ); -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_cmac_self_test( int verbose ); -#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_CMAC_H */ diff --git a/components/security/mbedtls/include/mbedtls/config.h b/components/security/mbedtls/include/mbedtls/config.h deleted file mode 100644 index 8c0fb34c..00000000 --- a/components/security/mbedtls/include/mbedtls/config.h +++ /dev/null @@ -1,195 +0,0 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - * - * 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) - */ - -#ifndef MBEDTLS_CONFIG_H -#define MBEDTLS_CONFIG_H - -#if !defined(CONFIG_MBEDTLS_ORIG) -/* System support */ -#define MBEDTLS_HAVE_ASM -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_FS_IO -//#define MBEDTLS_ECP_DP_CURVE25519_ENABLED -//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -//#define MBEDTLS_ECDH_C -#define MBEDTLS_ECP_C -//#define MBEDTLS_ECP_DP_SECP192R1_ENABLED -//#define MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -//#define MBEDTLS_ECP_DP_SECP384R1_ENABLED -//#define MBEDTLS_ECP_DP_SECP521R1_ENABLED -//#define MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define MBEDTLS_ECP_DP_SECP256K1_ENABLED - -/* mbed TLS feature support */ -#define MBEDTLS_GCM_C -#define MBEDTLS_CIPHER_MODE_CTR -#define MBEDTLS_CIPHER_MODE_CBC -#define MBEDTLS_CIPHER_PADDING_PKCS7 -#define MBEDTLS_CIPHER_PADDING_ZEROS -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_PKCS1_V21 -#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define MBEDTLS_SSL_PROTO_TLS1_2 -#define MBEDTLS_SSL_COOKIE_C -#define MBEDTLS_SSL_PROTO_DTLS -#define MBEDTLS_X509_CHECK_KEY_USAGE -#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE -#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH -#define MBEDTLS_SSL_SESSION_TICKETS -#define MBEDTLS_CIPHER_MODE_CFB -#define MBEDTLS_SSL_SERVER_NAME_INDICATION -//#define MBEDTLS_SSL_RENEGOTIATION -//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY -#define MBEDTLS_SSL_ALPN -//#define MBEDTLS_THREADING_C -//#define MBEDTLS_TIMING_C -//#define MBEDTLS_NO_PLATFORM_ENTROPY - -/* mbed TLS modules */ -#define MBEDTLS_AES_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_OID_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_CIPHER_C -#define MBEDTLS_CTR_DRBG_C -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_MD_C -#define MBEDTLS_MD5_C -#define MBEDTLS_NET_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_RSA_C -#define MBEDTLS_RSA_PRIV_ENABLED -#define MBEDTLS_SHA1_C -#define MBEDTLS_SHA256_C -#define MBEDTLS_SSL_CLI_C -#define MBEDTLS_SSL_SRV_C -#define MBEDTLS_SSL_TLS_C -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_USE_C -#define MBEDTLS_PEM_PARSE_C - -/* For test certificates */ -#define MBEDTLS_ERROR_C -#define MBEDTLS_ERROR_STRERROR_DUMMY -#define MBEDTLS_GENPRIME -#define MBEDTLS_BASE64_C -//#define MBEDTLS_SSL_ALL_ALERT_MESSAGES - -#define CONFIG_SSL_DEBUG -#if defined(CONFIG_SSL_DEBUG) -#define MBEDTLS_DEBUG_C -#endif - -#else /* CONFIG_MBEDTLS_ORIG */ - -/* System support */ -#define MBEDTLS_HAVE_ASM -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_PLATFORM_ALT - -/* mbed TLS feature support */ -#define MBEDTLS_CIPHER_MODE_CBC -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define MBEDTLS_SSL_PROTO_TLS1_2 -#define MBEDTLS_THREADING_C - -/* mbed TLS modules */ -#define MBEDTLS_AES_C -#define MBEDTLS_ASN1_PARSE_C - -#define MBEDTLS_OID_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_CIPHER_C -#define MBEDTLS_MD_C -#define MBEDTLS_MD5_C -#define MBEDTLS_NET_C -#define MBEDTLS_PK_C -#define MBEDTLS_PKMBEDTLS_THREADING_C_PARSE_C -#define MBEDTLS_RSMBEDTLS_THREADING_CA_C -#define MBEDTLS_SHMBEDTLS_THREADING_CA1_C -#define MBEDTLS_SHMBEDTLS_THREADING_CA256_C -#define MBEDTLS_SSMBEDTLS_THREADING_CL_CLI_C -#define MBEDTLS_SSL_TLS_C -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_USE_C -#define MBEDTLS_BASE64_C -#define MBEDTLS_PEM_PARSE_C -#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH -#define MBEDTLS_SSL_SESSION_TICKETS -#define MBEDTLS_CTR_DRBG_C -#define MBEDTLS_ENTROPY_C - -/* mbed DTLS modules */ -#define MBEDTLS_TIMING_C -#define MBEDTLS_SSL_COOKIE_C -#define MBEDTLS_SSL_PROTO_DTLS -#define MBEDTLS_SSL_DTLS_ANTI_REPLAY - -/* mbed TLS debug */ -#if defined(CONFIG_SSL_DEBUG) -#define MBEDTLS_DEBUG_C -#endif - -#define MBEDTLS_IOT_SPECIFIC -#define MBEDTLS_MD_ALT -#define MBEDTLS_PK_ALT -#define MBEDTLS_AES_ALT - -#if defined(MBEDTLS_MD_ALT) -#if defined(MBEDTLS_MD5_C) -#define MBEDTLS_MD5_ALT -#endif -#if defined(MBEDTLS_SHA1_C) -#define MBEDTLS_SHA1_ALT -#endif -#if defined(MBEDTLS_SHA256_C) -#define MBEDTLS_SHA256_ALT -#endif -#endif /* MBEDTLS_MD_ALT */ - -#endif /* CONFIG_MBEDTLS_ORIG */ - -#if defined(CONFIG_PLAT_AOS) -//#define MBEDTLS_THREADING_ALT -#define MBEDTLS_NET_ALT -#else -//#define MBEDTLS_THREADING_PTHREAD -#endif /* CONFIG_PLAT_AOS */ - -#define OTA_CONFIG_TLS -#if defined(OTA_CONFIG_TLS) -#define MBEDTLS_SSL_MAX_CONTENT_LEN (16 * 1024) /* Size of the input / output buffer */ -#else -#define MBEDTLS_SSL_MAX_CONTENT_LEN (16 * 1024) /* Size of the input / output buffer */ -#endif -#include "mbedtls/check_config.h" - -#endif /* MBEDTLS_CONFIG_H */ diff --git a/components/security/mbedtls/include/mbedtls/ctr_drbg.h b/components/security/mbedtls/include/mbedtls/ctr_drbg.h deleted file mode 100644 index 059d3c5c..00000000 --- a/components/security/mbedtls/include/mbedtls/ctr_drbg.h +++ /dev/null @@ -1,290 +0,0 @@ -/** - * \file ctr_drbg.h - * - * \brief CTR_DRBG based on AES-256 (NIST SP 800-90) - * - * 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) - */ -#ifndef MBEDTLS_CTR_DRBG_H -#define MBEDTLS_CTR_DRBG_H - -#include "aes.h" - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ -#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */ -#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */ -#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */ - -#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */ -#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */ -#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) -#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) - /**< The seed length (counter + AES key) */ - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -#else -#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -#endif -#endif - -#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) -#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -#endif - -#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) -#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -#endif - -#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) -#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -#endif - -#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) -#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ -#endif - -/* \} name SECTION: Module settings */ - -#define MBEDTLS_CTR_DRBG_PR_OFF 0 /**< No prediction resistance */ -#define MBEDTLS_CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief CTR_DRBG context structure - */ -typedef struct -{ - unsigned char counter[16]; /*!< counter (V) */ - int reseed_counter; /*!< reseed counter */ - int prediction_resistance; /*!< enable prediction resistance (Automatic - reseed before every random generation) */ - size_t entropy_len; /*!< amount of entropy grabbed on each - (re)seed */ - int reseed_interval; /*!< reseed interval */ - - mbedtls_aes_context aes_ctx; /*!< AES context */ - - /* - * Callbacks (Entropy) - */ - int (*f_entropy)(void *, unsigned char *, size_t); - - void *p_entropy; /*!< context for the entropy function */ - -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} -mbedtls_ctr_drbg_context; - -/** - * \brief CTR_DRBG context initialization - * Makes the context ready for mbedtls_ctr_drbg_seed() or - * mbedtls_ctr_drbg_free(). - * - * \param ctx CTR_DRBG context to be initialized - */ -void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); - -/** - * \brief CTR_DRBG initial seeding - * Seed and setup entropy source for future reseeds. - * - * Note: Personalization data can be provided in addition to the more generic - * entropy source to make this instantiation as unique as possible. - * - * \param ctx CTR_DRBG context to be seeded - * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer - * length) - * \param p_entropy Entropy context - * \param custom Personalization data (Device specific identifiers) - * (Can be NULL) - * \param len Length of personalization data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ); - -/** - * \brief Clear CTR_CRBG context data - * - * \param ctx CTR_DRBG context to clear - */ -void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); - -/** - * \brief Enable / disable prediction resistance (Default: Off) - * - * Note: If enabled, entropy is used for ctx->entropy_len before each call! - * Only use this if you have ample supply of good entropy! - * - * \param ctx CTR_DRBG context - * \param resistance MBEDTLS_CTR_DRBG_PR_ON or MBEDTLS_CTR_DRBG_PR_OFF - */ -void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, - int resistance ); - -/** - * \brief Set the amount of entropy grabbed on each (re)seed - * (Default: MBEDTLS_CTR_DRBG_ENTROPY_LEN) - * - * \param ctx CTR_DRBG context - * \param len Amount of entropy to grab - */ -void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, - size_t len ); - -/** - * \brief Set the reseed interval - * (Default: MBEDTLS_CTR_DRBG_RESEED_INTERVAL) - * - * \param ctx CTR_DRBG context - * \param interval Reseed interval - */ -void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, - int interval ); - -/** - * \brief CTR_DRBG reseeding (extracts data from entropy source) - * - * \param ctx CTR_DRBG context - * \param additional Additional data to add to state (Can be NULL) - * \param len Length of additional data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t len ); - -/** - * \brief CTR_DRBG update state - * - * \param ctx CTR_DRBG context - * \param additional Additional data to update state with - * \param add_len Length of additional data - * - * \note If add_len is greater than MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, - * only the first MBEDTLS_CTR_DRBG_MAX_SEED_INPUT bytes are used, - * the remaining ones are silently discarded. - */ -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); - -/** - * \brief CTR_DRBG generate random with additional update input - * - * Note: Automatically reseeds if reseed_counter is reached. - * - * \param p_rng CTR_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * \param additional Additional data to update with (Can be NULL) - * \param add_len Length of additional data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG - */ -int mbedtls_ctr_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, size_t add_len ); - -/** - * \brief CTR_DRBG generate random - * - * Note: Automatically reseeds if reseed_counter is reached. - * - * \param p_rng CTR_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG - */ -int mbedtls_ctr_drbg_random( void *p_rng, - unsigned char *output, size_t output_len ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Write a seed file - * - * \param ctx CTR_DRBG context - * \param path Name of the file - * - * \return 0 if successful, - * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); - -/** - * \brief Read and update a seed file. Seed is added to this - * instance - * - * \param ctx CTR_DRBG context - * \param path Name of the file - * - * \return 0 if successful, - * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or - * MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG - */ -int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_ctr_drbg_self_test( int verbose ); - -/* Internal functions (do not call directly) */ -int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, - int (*)(void *, unsigned char *, size_t), void *, - const unsigned char *, size_t, size_t ); - -#ifdef __cplusplus -} -#endif - -#endif /* ctr_drbg.h */ diff --git a/components/security/mbedtls/include/mbedtls/debug.h b/components/security/mbedtls/include/mbedtls/debug.h deleted file mode 100644 index d198afa7..00000000 --- a/components/security/mbedtls/include/mbedtls/debug.h +++ /dev/null @@ -1,238 +0,0 @@ -/** - * \file debug.h - * - * \brief Functions for controlling and providing debug output from the library. - * - * 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) - */ -#ifndef MBEDTLS_DEBUG_H -#define MBEDTLS_DEBUG_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "ssl.h" - -#if defined(MBEDTLS_ECP_C) -#include "ecp.h" -#endif - -#if defined(MBEDTLS_DEBUG_C) - -#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ - -#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ - mbedtls_debug_print_msg( ssl, level, "file1", __LINE__, \ - MBEDTLS_DEBUG_STRIP_PARENS args ) - -#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ - mbedtls_debug_print_ret( ssl, level, "file1", __LINE__, text, ret ) - -#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ - mbedtls_debug_print_buf( ssl, level, "file1", __LINE__, text, buf, len ) - -#if defined(MBEDTLS_BIGNUM_C) -#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ - mbedtls_debug_print_mpi( ssl, level, "file1", __LINE__, text, X ) -#endif - -#if defined(MBEDTLS_ECP_C) -#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ - mbedtls_debug_print_ecp( ssl, level, "file1", __LINE__, text, X ) -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ - mbedtls_debug_print_crt( ssl, level, "file1", __LINE__, text, crt ) -#endif - -#define MBEDTLS_DEBUG_BUF( level, text, buf, len ) \ - mbedtls_debug_print_buf( ssl, level, "file1", __LINE__, text, buf, len ) - -#define MBEDTLS_ALT_DEBUG_BUF( level, text, buf, len ) \ - mbedtls_debug_print_data(level, "file1", __LINE__, text, buf, len ) -#else /* MBEDTLS_DEBUG_C */ - -#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) -#define MBEDTLS_ALT_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) - -#endif /* MBEDTLS_DEBUG_C */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Set the threshold error level to handle globally all debug output. - * Debug messages that have a level over the threshold value are - * discarded. - * (Default value: 0 = No debug ) - * - * \param threshold theshold level of messages to filter on. Messages at a - * higher level will be discarded. - * - Debug levels - * - 0 No debug - * - 1 Error - * - 2 State change - * - 3 Informational - * - 4 Verbose - */ -void mbedtls_debug_set_threshold( int threshold ); - -/** - * \brief Print a message to the debug output. This function is always used - * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl - * context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the message has occurred in - * \param line line number the message has occurred at - * \param format format specifier, in printf format - * \param ... variables used by the format specifier - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *format, ... ); - -/** - * \brief Print the return value of a function to the debug output. This - * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text the name of the function that returned the error - * \param ret the return code value - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret ); - -/** - * \brief Output a buffer of size len bytes to the debug output. This function - * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the buffer being dumped. Normally the - * variable or buffer name - * \param buf the buffer to be outputted - * \param len length of the buffer - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text, - const unsigned char *buf, size_t len ); - -#if defined(MBEDTLS_BIGNUM_C) -/** - * \brief Print a MPI variable to the debug output. This function is always - * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the - * ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the MPI being output. Normally the - * variable name - * \param X the MPI variable - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_mpi *X ); -#endif - -#if defined(MBEDTLS_ECP_C) -/** - * \brief Print an ECP point to the debug output. This function is always - * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the - * ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the ECP point being output. Normally the - * variable name - * \param X the ECP point - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_ecp_point *X ); -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Print a X.509 certificate structure to the debug output. This - * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the certificate being output - * \param crt X.509 certificate structure - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_x509_crt *crt ); - -void mbedtls_debug_print_data(int level, - const char *file, int line, - const char *name, const unsigned char *data, int len); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* debug.h */ - diff --git a/components/security/mbedtls/include/mbedtls/des.h b/components/security/mbedtls/include/mbedtls/des.h deleted file mode 100644 index 5ca2ecf2..00000000 --- a/components/security/mbedtls/include/mbedtls/des.h +++ /dev/null @@ -1,306 +0,0 @@ -/** - * \file des.h - * - * \brief DES block cipher - * - * 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) - */ -#ifndef MBEDTLS_DES_H -#define MBEDTLS_DES_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#define MBEDTLS_DES_ENCRYPT 1 -#define MBEDTLS_DES_DECRYPT 0 - -#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ - -#define MBEDTLS_DES_KEY_SIZE 8 - -#if !defined(MBEDTLS_DES_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief DES context structure - */ -typedef struct -{ - uint32_t sk[32]; /*!< DES subkeys */ -} -mbedtls_des_context; - -/** - * \brief Triple-DES context structure - */ -typedef struct -{ - uint32_t sk[96]; /*!< 3DES subkeys */ -} -mbedtls_des3_context; - -/** - * \brief Initialize DES context - * - * \param ctx DES context to be initialized - */ -void mbedtls_des_init( mbedtls_des_context *ctx ); - -/** - * \brief Clear DES context - * - * \param ctx DES context to be cleared - */ -void mbedtls_des_free( mbedtls_des_context *ctx ); - -/** - * \brief Initialize Triple-DES context - * - * \param ctx DES3 context to be initialized - */ -void mbedtls_des3_init( mbedtls_des3_context *ctx ); - -/** - * \brief Clear Triple-DES context - * - * \param ctx DES3 context to be cleared - */ -void mbedtls_des3_free( mbedtls_des3_context *ctx ); - -/** - * \brief Set key parity on the given key to odd. - * - * DES keys are 56 bits long, but each byte is padded with - * a parity bit to allow verification. - * - * \param key 8-byte secret key - */ -void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief Check that key parity on the given key is odd. - * - * DES keys are 56 bits long, but each byte is padded with - * a parity bit to allow verification. - * - * \param key 8-byte secret key - * - * \return 0 is parity was ok, 1 if parity was not correct. - */ -int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief Check that key is not a weak or semi-weak DES key - * - * \param key 8-byte secret key - * - * \return 0 if no weak key was found, 1 if a weak key was identified. - */ -int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief DES key schedule (56-bit, encryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - * - * \return 0 - */ -int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief DES key schedule (56-bit, decryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - * - * \return 0 - */ -int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief Triple-DES key schedule (112-bit, encryption) - * - * \param ctx 3DES context to be initialized - * \param key 16-byte secret key - * - * \return 0 - */ -int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); - -/** - * \brief Triple-DES key schedule (112-bit, decryption) - * - * \param ctx 3DES context to be initialized - * \param key 16-byte secret key - * - * \return 0 - */ -int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); - -/** - * \brief Triple-DES key schedule (168-bit, encryption) - * - * \param ctx 3DES context to be initialized - * \param key 24-byte secret key - * - * \return 0 - */ -int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); - -/** - * \brief Triple-DES key schedule (168-bit, decryption) - * - * \param ctx 3DES context to be initialized - * \param key 24-byte secret key - * - * \return 0 - */ -int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); - -/** - * \brief DES-ECB block encryption/decryption - * - * \param ctx DES context - * \param input 64-bit input block - * \param output 64-bit output block - * - * \return 0 if successful - */ -int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief DES-CBC buffer encryption/decryption - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx DES context - * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - */ -int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -/** - * \brief 3DES-ECB block encryption/decryption - * - * \param ctx 3DES context - * \param input 64-bit input block - * \param output 64-bit output block - * - * \return 0 if successful - */ -int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief 3DES-CBC buffer encryption/decryption - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx 3DES context - * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH - */ -int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -/** - * \brief Internal function for key expansion. - * (Only exposed to allow overriding it, - * see MBEDTLS_DES_SETKEY_ALT) - * - * \param SK Round keys - * \param key Base key - */ -void mbedtls_des_setkey( uint32_t SK[32], - const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_DES_ALT */ -#include "des_alt.h" -#endif /* MBEDTLS_DES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_des_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* des.h */ diff --git a/components/security/mbedtls/include/mbedtls/ecdh.h b/components/security/mbedtls/include/mbedtls/ecdh.h deleted file mode 100644 index 625a2819..00000000 --- a/components/security/mbedtls/include/mbedtls/ecdh.h +++ /dev/null @@ -1,214 +0,0 @@ -/** - * \file ecdh.h - * - * \brief Elliptic curve Diffie-Hellman - * - * 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) - */ -#ifndef MBEDTLS_ECDH_H -#define MBEDTLS_ECDH_H - -#include "ecp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * When importing from an EC key, select if it is our key or the peer's key - */ -typedef enum -{ - MBEDTLS_ECDH_OURS, - MBEDTLS_ECDH_THEIRS, -} mbedtls_ecdh_side; - -/** - * \brief ECDH context structure - */ -typedef struct -{ - mbedtls_ecp_group grp; /*!< elliptic curve used */ - mbedtls_mpi d; /*!< our secret value (private key) */ - mbedtls_ecp_point Q; /*!< our public value (public key) */ - mbedtls_ecp_point Qp; /*!< peer's public value (public key) */ - mbedtls_mpi z; /*!< shared secret */ - int point_format; /*!< format for point export in TLS messages */ - mbedtls_ecp_point Vi; /*!< blinding value (for later) */ - mbedtls_ecp_point Vf; /*!< un-blinding value (for later) */ - mbedtls_mpi _d; /*!< previous d (for later) */ -} -mbedtls_ecdh_context; - -/** - * \brief Generate a public key. - * Raw function that only does the core computation. - * - * \param grp ECP group - * \param d Destination MPI (secret exponent, aka private key) - * \param Q Destination point (public key) - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Compute shared secret - * Raw function that only does the core computation. - * - * \param grp ECP group - * \param z Destination MPI (shared secret) - * \param Q Public key from other party - * \param d Our secret exponent (private key) - * \param f_rng RNG function (see notes) - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - * - * \note If f_rng is not NULL, it is used to implement - * countermeasures against potential elaborate timing - * attacks, see \c mbedtls_ecp_mul() for details. - */ -int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, - const mbedtls_ecp_point *Q, const mbedtls_mpi *d, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Initialize context - * - * \param ctx Context to initialize - */ -void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); - -/** - * \brief Free context - * - * \param ctx Context to free - */ -void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); - -/** - * \brief Generate a public key and a TLS ServerKeyExchange payload. - * (First function used by a TLS server for ECDHE.) - * - * \param ctx ECDH context - * \param olen number of chars written - * \param buf destination buffer - * \param blen length of buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note This function assumes that ctx->grp has already been - * properly set (for example using mbedtls_ecp_group_load). - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Parse and procress a TLS ServerKeyExhange payload. - * (First function used by a TLS client for ECDHE.) - * - * \param ctx ECDH context - * \param buf pointer to start of input buffer - * \param end one past end of buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, - const unsigned char **buf, const unsigned char *end ); - -/** - * \brief Setup an ECDH context from an EC key. - * (Used by clients and servers in place of the - * ServerKeyEchange for static ECDH: import ECDH parameters - * from a certificate's EC key information.) - * - * \param ctx ECDH constext to set - * \param key EC key to use - * \param side Is it our key (1) or the peer's key (0) ? - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, - mbedtls_ecdh_side side ); - -/** - * \brief Generate a public key and a TLS ClientKeyExchange payload. - * (Second function used by a TLS client for ECDH(E).) - * - * \param ctx ECDH context - * \param olen number of bytes actually written - * \param buf destination buffer - * \param blen size of destination buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Parse and process a TLS ClientKeyExchange payload. - * (Second function used by a TLS server for ECDH(E).) - * - * \param ctx ECDH context - * \param buf start of input buffer - * \param blen length of input buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, - const unsigned char *buf, size_t blen ); - -/** - * \brief Derive and export the shared secret. - * (Last function used by both TLS client en servers.) - * - * \param ctx ECDH context - * \param olen number of bytes written - * \param buf destination buffer - * \param blen buffer length - * \param f_rng RNG function, see notes for \c mbedtls_ecdh_compute_shared() - * \param p_rng RNG parameter - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -#ifdef __cplusplus -} -#endif - -#endif /* ecdh.h */ diff --git a/components/security/mbedtls/include/mbedtls/ecdsa.h b/components/security/mbedtls/include/mbedtls/ecdsa.h deleted file mode 100644 index 52827d8d..00000000 --- a/components/security/mbedtls/include/mbedtls/ecdsa.h +++ /dev/null @@ -1,248 +0,0 @@ -/** - * \file ecdsa.h - * - * \brief Elliptic curve DSA - * - * 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) - */ -#ifndef MBEDTLS_ECDSA_H -#define MBEDTLS_ECDSA_H - -#include "ecp.h" -#include "md.h" - -/* - * RFC 4492 page 20: - * - * Ecdsa-Sig-Value ::= SEQUENCE { - * r INTEGER, - * s INTEGER - * } - * - * Size is at most - * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, - * twice that + 1 (tag) + 2 (len) for the sequence - * (assuming ECP_MAX_BYTES is less than 126 for r and s, - * and less than 124 (total len <= 255) for the sequence) - */ -#if MBEDTLS_ECP_MAX_BYTES > 124 -#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" -#endif -/** Maximum size of an ECDSA signature in bytes */ -#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) - -/** - * \brief ECDSA context structure - */ -typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Compute ECDSA signature of a previously hashed message - * - * \note The deterministic version is usually prefered. - * - * \param grp ECP group - * \param r First output integer - * \param s Second output integer - * \param d Private signing key - * \param buf Message hash - * \param blen Length of buf - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -/** - * \brief Compute ECDSA signature of a previously hashed message, - * deterministic version (RFC 6979). - * - * \param grp ECP group - * \param r First output integer - * \param s Second output integer - * \param d Private signing key - * \param buf Message hash - * \param blen Length of buf - * \param md_alg MD algorithm used to hash the message - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ); -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - -/** - * \brief Verify ECDSA signature of a previously hashed message - * - * \param grp ECP group - * \param buf Message hash - * \param blen Length of buf - * \param Q Public key to use for verification - * \param r First integer of the signature - * \param s Second integer of the signature - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); - -/** - * \brief Compute ECDSA signature and write it to buffer, - * serialized as defined in RFC 4492 page 20. - * (Not thread-safe to use same context in multiple threads) - * - * \note The deterministice version (RFC 6979) is used if - * MBEDTLS_ECDSA_DETERMINISTIC is defined. - * - * \param ctx ECDSA context - * \param md_alg Algorithm that was used to hash the message - * \param hash Message hash - * \param hlen Length of hash - * \param sig Buffer that will hold the signature - * \param slen Length of the signature written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note The "sig" buffer must be at least as large as twice the - * size of the curve used, plus 9 (eg. 73 bytes if a 256-bit - * curve is used). MBEDTLS_ECDSA_MAX_LEN is always safe. - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX, MBEDTLS_ERR_MPI_XXX or - * MBEDTLS_ERR_ASN1_XXX error code - */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Compute ECDSA signature and write it to buffer, - * serialized as defined in RFC 4492 page 20. - * Deterministic version, RFC 6979. - * (Not thread-safe to use same context in multiple threads) - * - * \deprecated Superseded by mbedtls_ecdsa_write_signature() in 2.0.0 - * - * \param ctx ECDSA context - * \param hash Message hash - * \param hlen Length of hash - * \param sig Buffer that will hold the signature - * \param slen Length of the signature written - * \param md_alg MD algorithm used to hash the message - * - * \note The "sig" buffer must be at least as large as twice the - * size of the curve used, plus 9 (eg. 73 bytes if a 256-bit - * curve is used). MBEDTLS_ECDSA_MAX_LEN is always safe. - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX, MBEDTLS_ERR_MPI_XXX or - * MBEDTLS_ERR_ASN1_XXX error code - */ -int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; -#undef MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - -/** - * \brief Read and verify an ECDSA signature - * - * \param ctx ECDSA context - * \param hash Message hash - * \param hlen Size of hash - * \param sig Signature to read and verify - * \param slen Size of sig - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, - * MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than siglen, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX error code - */ -int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen ); - -/** - * \brief Generate an ECDSA keypair on the given curve - * - * \param ctx ECDSA context in which the keypair should be stored - * \param gid Group (elliptic curve) to use. One of the various - * MBEDTLS_ECP_DP_XXX macros depending on configuration. - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 on success, or a MBEDTLS_ERR_ECP_XXX code. - */ -int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Set an ECDSA context from an EC key pair - * - * \param ctx ECDSA context to set - * \param key EC key to use - * - * \return 0 on success, or a MBEDTLS_ERR_ECP_XXX code. - */ -int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); - -/** - * \brief Initialize context - * - * \param ctx Context to initialize - */ -void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); - -/** - * \brief Free context - * - * \param ctx Context to free - */ -void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* ecdsa.h */ diff --git a/components/security/mbedtls/include/mbedtls/ecp.h b/components/security/mbedtls/include/mbedtls/ecp.h deleted file mode 100644 index bf9abeff..00000000 --- a/components/security/mbedtls/include/mbedtls/ecp.h +++ /dev/null @@ -1,684 +0,0 @@ -/** - * \file ecp.h - * - * \brief Elliptic curves over GF(p) - * - * 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) - */ -#ifndef MBEDTLS_ECP_H -#define MBEDTLS_ECP_H - -#include "bignum.h" - -/* - * ECP error codes - */ -#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ -#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ -#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ -#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ -#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ -#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ -#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ - -#if !defined(MBEDTLS_ECP_ALT) -/* - * default mbed TLS elliptic curve arithmetic implementation - * - * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an - * alternative implementation for the whole module and it will replace this - * one.) - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Domain parameters (curve, subgroup and generator) identifiers. - * - * Only curves over prime fields are supported. - * - * \warning This library does not support validation of arbitrary domain - * parameters. Therefore, only well-known domain parameters from trusted - * sources should be used. See mbedtls_ecp_group_load(). - */ -typedef enum -{ - MBEDTLS_ECP_DP_NONE = 0, - MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ - MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ - MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ - MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ - MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ - MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ - MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ - MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ - MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ - MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ - MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ - MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ -} mbedtls_ecp_group_id; - -/** - * Number of supported curves (plus one for NONE). - * - * (Montgomery curves excluded for now.) - */ -#define MBEDTLS_ECP_DP_MAX 12 - -/** - * Curve information for use by other modules - */ -typedef struct -{ - mbedtls_ecp_group_id grp_id; /*!< Internal identifier */ - uint16_t tls_id; /*!< TLS NamedCurve identifier */ - uint16_t bit_size; /*!< Curve size in bits */ - const char *name; /*!< Human-friendly name */ -} mbedtls_ecp_curve_info; - -/** - * \brief ECP point structure (jacobian coordinates) - * - * \note All functions expect and return points satisfying - * the following condition: Z == 0 or Z == 1. (Other - * values of Z are used by internal functions only.) - * The point is zero, or "at infinity", if Z == 0. - * Otherwise, X and Y are its standard (affine) coordinates. - */ -typedef struct -{ - mbedtls_mpi X; /*!< the point's X coordinate */ - mbedtls_mpi Y; /*!< the point's Y coordinate */ - mbedtls_mpi Z; /*!< the point's Z coordinate */ -} -mbedtls_ecp_point; - -/** - * \brief ECP group structure - * - * We consider two types of curves equations: - * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) - * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) - * In both cases, a generator G for a prime-order subgroup is fixed. In the - * short weierstrass, this subgroup is actually the whole curve, and its - * cardinal is denoted by N. - * - * In the case of Short Weierstrass curves, our code requires that N is an odd - * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.) - * - * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is - * the quantity actually used in the formulas. Also, nbits is not the size of N - * but the required size for private keys. - * - * If modp is NULL, reduction modulo P is done using a generic algorithm. - * Otherwise, it must point to a function that takes an mbedtls_mpi in the range - * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more - * than pbits, so that the integer may be efficiently brought in the 0..P-1 - * range by a few additions or substractions. It must return 0 on success and - * non-zero on failure. - */ -typedef struct -{ - mbedtls_ecp_group_id id; /*!< internal group identifier */ - mbedtls_mpi P; /*!< prime modulus of the base field */ - mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ - mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */ - mbedtls_ecp_point G; /*!< generator of the (sub)group used */ - mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */ - size_t pbits; /*!< number of bits in P */ - size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ - unsigned int h; /*!< internal: 1 if the constants are static */ - int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */ - int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */ - int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */ - void *t_data; /*!< unused */ - mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ - size_t T_size; /*!< number for pre-computed points */ -} -mbedtls_ecp_group; - -/** - * \brief ECP key pair structure - * - * A generic key pair that could be used for ECDSA, fixed ECDH, etc. - * - * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. - */ -typedef struct -{ - mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ - mbedtls_mpi d; /*!< our secret value */ - mbedtls_ecp_point Q; /*!< our public value */ -} -mbedtls_ecp_keypair; - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_ECP_MAX_BITS) -/** - * Maximum size of the groups (that is, of N and P) - */ -#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ -#endif - -#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) -#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) - -#if !defined(MBEDTLS_ECP_WINDOW_SIZE) -/* - * Maximum "window" size used for point multiplication. - * Default: 6. - * Minimum value: 2. Maximum value: 7. - * - * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) - * points used for point multiplication. This value is directly tied to EC - * peak memory usage, so decreasing it by one should roughly cut memory usage - * by two (if large curves are in use). - * - * Reduction in size may reduce speed, but larger curves are impacted first. - * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): - * w-size: 6 5 4 3 2 - * 521 145 141 135 120 97 - * 384 214 209 198 177 146 - * 256 320 320 303 262 226 - - * 224 475 475 453 398 342 - * 192 640 640 633 587 476 - */ -#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ -#endif /* MBEDTLS_ECP_WINDOW_SIZE */ - -#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) -/* - * Trade memory for speed on fixed-point multiplication. - * - * This speeds up repeated multiplication of the generator (that is, the - * multiplication in ECDSA signatures, and half of the multiplications in - * ECDSA verification and ECDHE) by a factor roughly 3 to 4. - * - * The cost is increasing EC peak memory usage by a factor roughly 2. - * - * Change this value to 0 to reduce peak memory usage. - */ -#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ -#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ - -/* \} name SECTION: Module settings */ - -/* - * Point formats, from RFC 4492's enum ECPointFormat - */ -#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ -#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */ - -/* - * Some other constants from RFC 4492 - */ -#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ - -/** - * \brief Get the list of supported curves in order of preferrence - * (full information) - * - * \return A statically allocated array, the last entry is 0. - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); - -/** - * \brief Get the list of supported curves in order of preferrence - * (grp_id only) - * - * \return A statically allocated array, - * terminated with MBEDTLS_ECP_DP_NONE. - */ -const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); - -/** - * \brief Get curve information from an internal group identifier - * - * \param grp_id A MBEDTLS_ECP_DP_XXX value - * - * \return The associated curve information or NULL - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); - -/** - * \brief Get curve information from a TLS NamedCurve value - * - * \param tls_id A MBEDTLS_ECP_DP_XXX value - * - * \return The associated curve information or NULL - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); - -/** - * \brief Get curve information from a human-readable name - * - * \param name The name - * - * \return The associated curve information or NULL - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); - -/** - * \brief Initialize a point (as zero) - */ -void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); - -/** - * \brief Initialize a group (to something meaningless) - */ -void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); - -/** - * \brief Initialize a key pair (as an invalid one) - */ -void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); - -/** - * \brief Free the components of a point - */ -void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); - -/** - * \brief Free the components of an ECP group - */ -void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); - -/** - * \brief Free the components of a key pair - */ -void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); - -/** - * \brief Copy the contents of point Q into P - * - * \param P Destination point - * \param Q Source point - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); - -/** - * \brief Copy the contents of a group object - * - * \param dst Destination group - * \param src Source group - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); - -/** - * \brief Set a point to zero - * - * \param pt Destination point - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); - -/** - * \brief Tell if a point is zero - * - * \param pt Point to test - * - * \return 1 if point is zero, 0 otherwise - */ -int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); - -/** - * \brief Compare two points - * - * \note This assumes the points are normalized. Otherwise, - * they may compare as "not equal" even if they are. - * - * \param P First point to compare - * \param Q Second point to compare - * - * \return 0 if the points are equal, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise - */ -int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q ); - -/** - * \brief Import a non-zero point from two ASCII strings - * - * \param P Destination point - * \param radix Input numeric base - * \param x First affine coordinate as a null-terminated string - * \param y Second affine coordinate as a null-terminated string - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - */ -int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, - const char *x, const char *y ); - -/** - * \brief Export a point into unsigned binary data - * - * \param grp Group to which the point should belong - * \param P Point to export - * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro - * \param olen Length of the actual output - * \param buf Output buffer - * \param buflen Length of the output buffer - * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL - */ -int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, - int format, size_t *olen, - unsigned char *buf, size_t buflen ); - -/** - * \brief Import a point from unsigned binary data - * - * \param grp Group to which the point should belong - * \param P Point to import - * \param buf Input buffer - * \param ilen Actual length of input - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format - * is not implemented. - * - * \note This function does NOT check that the point actually - * belongs to the given group, see mbedtls_ecp_check_pubkey() for - * that. - */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, - const unsigned char *buf, size_t ilen ); - -/** - * \brief Import a point from a TLS ECPoint record - * - * \param grp ECP group used - * \param pt Destination point - * \param buf $(Start of input buffer) - * \param len Buffer length - * - * \note buf is updated to point right after the ECPoint on exit - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid - */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t len ); - -/** - * \brief Export a point as a TLS ECPoint record - * - * \param grp ECP group used - * \param pt Point to export - * \param format Export format - * \param olen length of data written - * \param buf Buffer to write to - * \param blen Buffer length - * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL - */ -int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, - int format, size_t *olen, - unsigned char *buf, size_t blen ); - -/** - * \brief Set a group using well-known domain parameters - * - * \param grp Destination group - * \param index Index in the list of well-known domain parameters - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups - * - * \note Index should be a value of RFC 4492's enum NamedCurve, - * usually in the form of a MBEDTLS_ECP_DP_XXX macro. - */ -int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id index ); - -/** - * \brief Set a group from a TLS ECParameters record - * - * \param grp Destination group - * \param buf &(Start of input buffer) - * \param len Buffer length - * - * \note buf is updated to point right after ECParameters on exit - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid - */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); - -/** - * \brief Write the TLS ECParameters record for a group - * - * \param grp ECP group used - * \param olen Number of bytes actually written - * \param buf Buffer to write to - * \param blen Buffer length - * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL - */ -int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, - unsigned char *buf, size_t blen ); - -/** - * \brief Multiplication by an integer: R = m * P - * (Not thread-safe to use same group in multiple threads) - * - * \note In order to prevent timing attacks, this function - * executes the exact same sequence of (base field) - * operations for any valid m. It avoids any if-branch or - * array index depending on the value of m. - * - * \note If f_rng is not NULL, it is used to randomize intermediate - * results in order to prevent potential timing attacks - * targeting these results. It is recommended to always - * provide a non-NULL f_rng (the overhead is negligible). - * - * \param grp ECP group - * \param R Destination point - * \param m Integer by which to multiply - * \param P Point to multiply - * \param f_rng RNG function (see notes) - * \param p_rng RNG parameter - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey - * or P is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Multiplication and addition of two points by integers: - * R = m * P + n * Q - * (Not thread-safe to use same group in multiple threads) - * - * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee - * a constant execution flow and timing. - * - * \param grp ECP group - * \param R Destination point - * \param m Integer by which to multiply P - * \param P Point to multiply by m - * \param n Integer by which to multiply Q - * \param Q Point to be multiplied by n - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey - * or P or Q is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); - -/** - * \brief Check that a point is a valid public key on this curve - * - * \param grp Curve/group the point should belong to - * \param pt Point to check - * - * \return 0 if point is a valid public key, - * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. - * - * \note This function only checks the point is non-zero, has valid - * coordinates and lies on the curve, but not that it is - * indeed a multiple of G. This is additional check is more - * expensive, isn't required by standards, and shouldn't be - * necessary if the group used has a small cofactor. In - * particular, it is useless for the NIST groups which all - * have a cofactor of 1. - * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. - */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); - -/** - * \brief Check that an mbedtls_mpi is a valid private key for this curve - * - * \param grp Group used - * \param d Integer to check - * - * \return 0 if point is a valid private key, - * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. - * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. - */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); - -/** - * \brief Generate a keypair with configurable base point - * - * \param grp ECP group - * \param G Chosen base point - * \param d Destination MPI (secret part) - * \param Q Destination point (public part) - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. - */ -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Generate a keypair - * - * \param grp ECP group - * \param d Destination MPI (secret part) - * \param Q Destination point (public part) - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. - */ -int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Generate a keypair - * - * \param grp_id ECP group identifier - * \param key Destination keypair - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Check a public-private key pair - * - * \param pub Keypair structure holding a public key - * \param prv Keypair structure holding a private (plus public) key - * - * \return 0 if successful (keys are valid and match), or - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or - * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code. - */ -int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); - -#if defined(MBEDTLS_SELF_TEST) - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_ecp_self_test( int verbose ); - -#endif /* MBEDTLS_SELF_TEST */ - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_ECP_ALT */ -#include "ecp_alt.h" -#endif /* MBEDTLS_ECP_ALT */ - -#endif /* ecp.h */ diff --git a/components/security/mbedtls/include/mbedtls/ecp_internal.h b/components/security/mbedtls/include/mbedtls/ecp_internal.h deleted file mode 100644 index 18040697..00000000 --- a/components/security/mbedtls/include/mbedtls/ecp_internal.h +++ /dev/null @@ -1,293 +0,0 @@ -/** - * \file ecp_internal.h - * - * \brief Function declarations for alternative implementation of elliptic curve - * point arithmetic. - */ -/* - * Copyright (C) 2016, 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) - */ - -/* - * References: - * - * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. - * - * - * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis - * for elliptic curve cryptosystems. In : Cryptographic Hardware and - * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. - * - * - * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to - * render ECC resistant against Side Channel Attacks. IACR Cryptology - * ePrint Archive, 2004, vol. 2004, p. 342. - * - * - * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. - * - * - * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic - * Curve Cryptography. - * - * [6] Digital Signature Standard (DSS), FIPS 186-4. - * - * - * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer - * Security (TLS), RFC 4492. - * - * - * [8] - * - * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. - * Springer Science & Business Media, 1 Aug 2000 - */ - -#ifndef MBEDTLS_ECP_INTERNAL_H -#define MBEDTLS_ECP_INTERNAL_H - -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - -/** - * \brief Indicate if the Elliptic Curve Point module extension can - * handle the group. - * - * \param grp The pointer to the elliptic curve group that will be the - * basis of the cryptographic computations. - * - * \return Non-zero if successful. - */ -unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); - -/** - * \brief Initialise the Elliptic Curve Point module extension. - * - * If mbedtls_internal_ecp_grp_capable returns true for a - * group, this function has to be able to initialise the - * module for it. - * - * This module can be a driver to a crypto hardware - * accelerator, for which this could be an initialise function. - * - * \param grp The pointer to the group the module needs to be - * initialised for. - * - * \return 0 if successful. - */ -int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); - -/** - * \brief Frees and deallocates the Elliptic Curve Point module - * extension. - * - * \param grp The pointer to the group the module was initialised for. - */ -void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); - -#if defined(ECP_SHORTWEIERSTRASS) - -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) -/** - * \brief Randomize jacobian coordinates: - * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. - * - * \param grp Pointer to the group representing the curve. - * - * \param pt The point on the curve to be randomised, given with Jacobian - * coordinates. - * - * \param f_rng A function pointer to the random number generator. - * - * \param p_rng A pointer to the random number generator state. - * - * \return 0 if successful. - */ -int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#endif - -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) -/** - * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. - * - * The coordinates of Q must be normalized (= affine), - * but those of P don't need to. R is not normalized. - * - * This function is used only as a subrutine of - * ecp_mul_comb(). - * - * Special cases: (1) P or Q is zero, (2) R is zero, - * (3) P == Q. - * None of these cases can happen as intermediate step in - * ecp_mul_comb(): - * - at each step, P, Q and R are multiples of the base - * point, the factor being less than its order, so none of - * them is zero; - * - Q is an odd multiple of the base point, P an even - * multiple, due to the choice of precomputed points in the - * modified comb method. - * So branches for these cases do not leak secret information. - * - * We accept Q->Z being unset (saving memory in tables) as - * meaning 1. - * - * Cost in field operations if done by [5] 3.22: - * 1A := 8M + 3S - * - * \param grp Pointer to the group representing the curve. - * - * \param R Pointer to a point structure to hold the result. - * - * \param P Pointer to the first summand, given with Jacobian - * coordinates - * - * \param Q Pointer to the second summand, given with affine - * coordinates. - * - * \return 0 if successful. - */ -int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q ); -#endif - -/** - * \brief Point doubling R = 2 P, Jacobian coordinates. - * - * Cost: 1D := 3M + 4S (A == 0) - * 4M + 4S (A == -3) - * 3M + 6S + 1a otherwise - * when the implementation is based on the "dbl-1998-cmo-2" - * doubling formulas in [8] and standard optimizations are - * applied when curve parameter A is one of { 0, -3 }. - * - * \param grp Pointer to the group representing the curve. - * - * \param R Pointer to a point structure to hold the result. - * - * \param P Pointer to the point that has to be doubled, given with - * Jacobian coordinates. - * - * \return 0 if successful. - */ -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) -int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); -#endif - -/** - * \brief Normalize jacobian coordinates of an array of (pointers to) - * points. - * - * Using Montgomery's trick to perform only one inversion mod P - * the cost is: - * 1N(t) := 1I + (6t - 3)M + 1S - * (See for example Algorithm 10.3.4. in [9]) - * - * This function is used only as a subrutine of - * ecp_mul_comb(). - * - * Warning: fails (returning an error) if one of the points is - * zero! - * This should never happen, see choice of w in ecp_mul_comb(). - * - * \param grp Pointer to the group representing the curve. - * - * \param T Array of pointers to the points to normalise. - * - * \param t_len Number of elements in the array. - * - * \return 0 if successful, - * an error if one of the points is zero. - */ -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) -int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *T[], size_t t_len ); -#endif - -/** - * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. - * - * Cost in field operations if done by [5] 3.2.1: - * 1N := 1I + 3M + 1S - * - * \param grp Pointer to the group representing the curve. - * - * \param pt pointer to the point to be normalised. This is an - * input/output parameter. - * - * \return 0 if successful. - */ -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) -int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *pt ); -#endif - -#endif /* ECP_SHORTWEIERSTRASS */ - -#if defined(ECP_MONTGOMERY) - -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) -int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); -#endif - -/** - * \brief Randomize projective x/z coordinates: - * (X, Z) -> (l X, l Z) for random l - * - * \param grp pointer to the group representing the curve - * - * \param P the point on the curve to be randomised given with - * projective coordinates. This is an input/output parameter. - * - * \param f_rng a function pointer to the random number generator - * - * \param p_rng a pointer to the random number generator state - * - * \return 0 if successful - */ -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) -int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#endif - -/** - * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. - * - * \param grp pointer to the group representing the curve - * - * \param P pointer to the point to be normalised. This is an - * input/output parameter. - * - * \return 0 if successful - */ -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) -int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *P ); -#endif - -#endif /* ECP_MONTGOMERY */ - -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - -#endif /* ecp_internal.h */ - diff --git a/components/security/mbedtls/include/mbedtls/entropy.h b/components/security/mbedtls/include/mbedtls/entropy.h deleted file mode 100644 index 747aca4d..00000000 --- a/components/security/mbedtls/include/mbedtls/entropy.h +++ /dev/null @@ -1,287 +0,0 @@ -/** - * \file entropy.h - * - * \brief Entropy accumulator implementation - * - * Copyright (C) 2006-2016, 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) - */ -#ifndef MBEDTLS_ENTROPY_H -#define MBEDTLS_ENTROPY_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -#include "sha512.h" -#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR -#else -#if defined(MBEDTLS_SHA256_C) -#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR -#include "sha256.h" -#endif -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -#if defined(MBEDTLS_HAVEGE_C) -#include "havege.h" -#endif - -#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ -#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ -#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ -#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ -#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) -#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ -#endif - -#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) -#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ -#endif - -/* \} name SECTION: Module settings */ - -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) -#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ -#else -#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ -#endif - -#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ -#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES - -#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ -#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Entropy poll callback pointer - * - * \param data Callback-specific data pointer - * \param output Data to fill - * \param len Maximum size to provide - * \param olen The actual amount of bytes put into the buffer (Can be 0) - * - * \return 0 if no critical failures occurred, - * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise - */ -typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, - size_t *olen); - -/** - * \brief Entropy source state - */ -typedef struct -{ - mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ - void * p_source; /**< The callback data pointer */ - size_t size; /**< Amount received in bytes */ - size_t threshold; /**< Minimum bytes required before release */ - int strong; /**< Is the source strong? */ -} -mbedtls_entropy_source_state; - -/** - * \brief Entropy context structure - */ -typedef struct -{ -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_context accumulator; -#else - mbedtls_sha256_context accumulator; -#endif - int source_count; - mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_state havege_data; -#endif -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< mutex */ -#endif -#if defined(MBEDTLS_ENTROPY_NV_SEED) - int initial_entropy_run; -#endif -} -mbedtls_entropy_context; - -/** - * \brief Initialize the context - * - * \param ctx Entropy context to initialize - */ -void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); - -/** - * \brief Free the data in the context - * - * \param ctx Entropy context to free - */ -void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); - -/** - * \brief Adds an entropy source to poll - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param ctx Entropy context - * \param f_source Entropy function - * \param p_source Function data - * \param threshold Minimum required from source before entropy is released - * ( with mbedtls_entropy_func() ) (in bytes) - * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or - * MBEDTSL_ENTROPY_SOURCE_WEAK. - * At least one strong source needs to be added. - * Weaker sources (such as the cycle counter) can be used as - * a complement. - * - * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES - */ -int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, - mbedtls_entropy_f_source_ptr f_source, void *p_source, - size_t threshold, int strong ); - -/** - * \brief Trigger an extra gather poll for the accumulator - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param ctx Entropy context - * - * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED - */ -int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); - -/** - * \brief Retrieve entropy from the accumulator - * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param data Entropy context - * \param output Buffer to fill - * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE - * - * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED - */ -int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); - -/** - * \brief Add data to the accumulator manually - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param ctx Entropy context - * \param data Data to add - * \param len Length of data - * - * \return 0 if successful - */ -int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, - const unsigned char *data, size_t len ); - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -/** - * \brief Trigger an update of the seed file in NV by using the - * current entropy pool. - * - * \param ctx Entropy context - * - * \return 0 if successful - */ -int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Write a seed file - * - * \param ctx Entropy context - * \param path Name of the file - * - * \return 0 if successful, - * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or - * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED - */ -int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); - -/** - * \brief Read and update a seed file. Seed is added to this - * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are - * read from the seed file. The rest is ignored. - * - * \param ctx Entropy context - * \param path Name of the file - * - * \return 0 if successful, - * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, - * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED - */ -int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_SELF_TEST) -/** - * \brief Checkup routine - * - * This module self-test also calls the entropy self-test, - * mbedtls_entropy_source_self_test(); - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_entropy_self_test( int verbose ); - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) -/** - * \brief Checkup routine - * - * Verifies the integrity of the hardware entropy source - * provided by the function 'mbedtls_hardware_poll()'. - * - * Note this is the only hardware entropy source that is known - * at link time, and other entropy sources configured - * dynamically at runtime by the function - * mbedtls_entropy_add_source() will not be tested. - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_entropy_source_self_test( int verbose ); -#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ -#endif /* MBEDTLS_SELF_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* entropy.h */ diff --git a/components/security/mbedtls/include/mbedtls/entropy_poll.h b/components/security/mbedtls/include/mbedtls/entropy_poll.h deleted file mode 100644 index 81258d5f..00000000 --- a/components/security/mbedtls/include/mbedtls/entropy_poll.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * \file entropy_poll.h - * - * \brief Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2016, 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) - */ -#ifndef MBEDTLS_ENTROPY_POLL_H -#define MBEDTLS_ENTROPY_POLL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Default thresholds for built-in sources, in bytes - */ -#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ -#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ -#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ -#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) -#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ -#endif - -/** - * \brief Entropy poll callback that provides 0 entropy. - */ -#if defined(MBEDTLS_TEST_NULL_ENTROPY) - int mbedtls_null_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) -/** - * \brief Platform-specific entropy poll callback - */ -int mbedtls_platform_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(MBEDTLS_HAVEGE_C) -/** - * \brief HAVEGE based entropy poll callback - * - * Requires an HAVEGE state as its data pointer. - */ -int mbedtls_havege_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(MBEDTLS_TIMING_C) -/** - * \brief mbedtls_timing_hardclock-based entropy poll callback - */ -int mbedtls_hardclock_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) -/** - * \brief Entropy poll callback for a hardware source - * - * \warning This is not provided by mbed TLS! - * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. - * - * \note This must accept NULL as its first argument. - */ -int mbedtls_hardware_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -/** - * \brief Entropy poll callback for a non-volatile seed file - * - * \note This must accept NULL as its first argument. - */ -int mbedtls_nv_seed_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* entropy_poll.h */ diff --git a/components/security/mbedtls/include/mbedtls/error.h b/components/security/mbedtls/include/mbedtls/error.h deleted file mode 100644 index 5e549f6b..00000000 --- a/components/security/mbedtls/include/mbedtls/error.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - * \file error.h - * - * \brief Error to string translation - * - * 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) - */ -#ifndef MBEDTLS_ERROR_H -#define MBEDTLS_ERROR_H - -#include - -/** - * Error code layout. - * - * Currently we try to keep all error codes within the negative space of 16 - * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In - * addition we'd like to give two layers of information on the error if - * possible. - * - * For that purpose the error codes are segmented in the following manner: - * - * 16 bit error code bit-segmentation - * - * 1 bit - Unused (sign bit) - * 3 bits - High level module ID - * 5 bits - Module-dependent error code - * 7 bits - Low level module errors - * - * For historical reasons, low-level error codes are divided in even and odd, - * even codes were assigned first, and -1 is reserved for other errors. - * - * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) - * - * Module Nr Codes assigned - * MPI 7 0x0002-0x0010 - * GCM 2 0x0012-0x0014 - * BLOWFISH 2 0x0016-0x0018 - * THREADING 3 0x001A-0x001E - * AES 2 0x0020-0x0022 - * CAMELLIA 2 0x0024-0x0026 - * XTEA 1 0x0028-0x0028 - * BASE64 2 0x002A-0x002C - * OID 1 0x002E-0x002E 0x000B-0x000B - * PADLOCK 1 0x0030-0x0030 - * DES 1 0x0032-0x0032 - * CTR_DBRG 4 0x0034-0x003A - * ENTROPY 3 0x003C-0x0040 0x003D-0x003F - * NET 11 0x0042-0x0052 0x0043-0x0045 - * ASN1 7 0x0060-0x006C - * PBKDF2 1 0x007C-0x007C - * HMAC_DRBG 4 0x0003-0x0009 - * CCM 2 0x000D-0x000F - * - * High-level module nr (3 bits - 0x0...-0x7...) - * Name ID Nr of Errors - * PEM 1 9 - * PKCS#12 1 4 (Started from top) - * X509 2 19 - * PKCS5 2 4 (Started from top) - * DHM 3 9 - * PK 3 14 (Started from top) - * RSA 4 9 - * ECP 4 8 (Started from top) - * MD 5 4 - * CIPHER 6 6 - * SSL 6 17 (Started from top) - * SSL 7 31 - * - * Module dependent error code (5 bits 0x.00.-0x.F8.) - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Translate a mbed TLS error code into a string representation, - * Result is truncated if necessary and always includes a terminating - * null byte. - * - * \param errnum error code - * \param buffer buffer to place representation in - * \param buflen length of the buffer - */ -void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); - -#ifdef __cplusplus -} -#endif - -#endif /* error.h */ diff --git a/components/security/mbedtls/include/mbedtls/gcm.h b/components/security/mbedtls/include/mbedtls/gcm.h deleted file mode 100644 index fccabb0d..00000000 --- a/components/security/mbedtls/include/mbedtls/gcm.h +++ /dev/null @@ -1,316 +0,0 @@ -/** - * \file gcm.h - * - * \brief This file contains GCM definitions and functions. - * - * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined - * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation - * (GCM), Natl. Inst. Stand. Technol. - * - * For more information on GCM, see NIST SP 800-38D: Recommendation for - * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. - * - */ -/* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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) - */ - -#ifndef MBEDTLS_GCM_H -#define MBEDTLS_GCM_H - -#include "cipher.h" - -#include - -#define MBEDTLS_GCM_ENCRYPT 1 -#define MBEDTLS_GCM_DECRYPT 0 - -#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ - -/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */ -#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ - -#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_GCM_ALT) - -/** - * \brief The GCM context structure. - */ -typedef struct mbedtls_gcm_context -{ - mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ - uint64_t HL[16]; /*!< Precalculated HTable low. */ - uint64_t HH[16]; /*!< Precalculated HTable high. */ - uint64_t len; /*!< The total length of the encrypted data. */ - uint64_t add_len; /*!< The total length of the additional data. */ - unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ - unsigned char y[16]; /*!< The Y working value. */ - unsigned char buf[16]; /*!< The buf working value. */ - int mode; /*!< The operation to perform: - #MBEDTLS_GCM_ENCRYPT or - #MBEDTLS_GCM_DECRYPT. */ -} -mbedtls_gcm_context; - -#else /* !MBEDTLS_GCM_ALT */ -#include "gcm_alt.h" -#endif /* !MBEDTLS_GCM_ALT */ - -/** - * \brief This function initializes the specified GCM context, - * to make references valid, and prepares the context - * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). - * - * The function does not bind the GCM context to a particular - * cipher, nor set the key. For this purpose, use - * mbedtls_gcm_setkey(). - * - * \param ctx The GCM context to initialize. This must not be \c NULL. - */ -void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); - -/** - * \brief This function associates a GCM context with a - * cipher algorithm and a key. - * - * \param ctx The GCM context. This must be initialized. - * \param cipher The 128-bit block cipher to use. - * \param key The encryption key. This must be a readable buffer of at - * least \p keybits bits. - * \param keybits The key size in bits. Valid options are: - *
  • 128 bits
  • - *
  • 192 bits
  • - *
  • 256 bits
- * - * \return \c 0 on success. - * \return A cipher-specific error code on failure. - */ -int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ); - -/** - * \brief This function performs GCM encryption or decryption of a buffer. - * - * \note For encryption, the output buffer can be the same as the - * input buffer. For decryption, the output buffer cannot be - * the same as input buffer. If the buffers overlap, the output - * buffer must trail at least 8 Bytes behind the input buffer. - * - * \warning When this function performs a decryption, it outputs the - * authentication tag and does not verify that the data is - * authentic. You should use this function to perform encryption - * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. - * - * \param ctx The GCM context to use for encryption or decryption. This - * must be initialized. - * \param mode The operation to perform: - * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. - * The ciphertext is written to \p output and the - * authentication tag is written to \p tag. - * - #MBEDTLS_GCM_DECRYPT to perform decryption. - * The plaintext is written to \p output and the - * authentication tag is written to \p tag. - * Note that this mode is not recommended, because it does - * not verify the authenticity of the data. For this reason, - * you should use mbedtls_gcm_auth_decrypt() instead of - * calling this function in decryption mode. - * \param length The length of the input data, which is equal to the length - * of the output data. - * \param iv The initialization vector. This must be a readable buffer of - * at least \p iv_len Bytes. - * \param iv_len The length of the IV. - * \param add The buffer holding the additional data. This must be of at - * least that size in Bytes. - * \param add_len The length of the additional data. - * \param input The buffer holding the input data. If \p length is greater - * than zero, this must be a readable buffer of at least that - * size in Bytes. - * \param output The buffer for holding the output data. If \p length is greater - * than zero, this must be a writable buffer of at least that - * size in Bytes. - * \param tag_len The length of the tag to generate. - * \param tag The buffer for holding the tag. This must be a readable - * buffer of at least \p tag_len Bytes. - * - * \return \c 0 if the encryption or decryption was performed - * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, - * this does not indicate that the data is authentic. - * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are - * not valid or a cipher-specific error code if the encryption - * or decryption failed. - */ -int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, - int mode, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *input, - unsigned char *output, - size_t tag_len, - unsigned char *tag ); - -/** - * \brief This function performs a GCM authenticated decryption of a - * buffer. - * - * \note For decryption, the output buffer cannot be the same as - * input buffer. If the buffers overlap, the output buffer - * must trail at least 8 Bytes behind the input buffer. - * - * \param ctx The GCM context. This must be initialized. - * \param length The length of the ciphertext to decrypt, which is also - * the length of the decrypted plaintext. - * \param iv The initialization vector. This must be a readable buffer - * of at least \p iv_len Bytes. - * \param iv_len The length of the IV. - * \param add The buffer holding the additional data. This must be of at - * least that size in Bytes. - * \param add_len The length of the additional data. - * \param tag The buffer holding the tag to verify. This must be a - * readable buffer of at least \p tag_len Bytes. - * \param tag_len The length of the tag to verify. - * \param input The buffer holding the ciphertext. If \p length is greater - * than zero, this must be a readable buffer of at least that - * size. - * \param output The buffer for holding the decrypted plaintext. If \p length - * is greater than zero, this must be a writable buffer of at - * least that size. - * - * \return \c 0 if successful and authenticated. - * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. - * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are - * not valid or a cipher-specific error code if the decryption - * failed. - */ -int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *tag, - size_t tag_len, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief This function starts a GCM encryption or decryption - * operation. - * - * \param ctx The GCM context. This must be initialized. - * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or - * #MBEDTLS_GCM_DECRYPT. - * \param iv The initialization vector. This must be a readable buffer of - * at least \p iv_len Bytes. - * \param iv_len The length of the IV. - * \param add The buffer holding the additional data, or \c NULL - * if \p add_len is \c 0. - * \param add_len The length of the additional data. If \c 0, - * \p add may be \c NULL. - * - * \return \c 0 on success. - */ -int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, - int mode, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len ); - -/** - * \brief This function feeds an input buffer into an ongoing GCM - * encryption or decryption operation. - * - * ` The function expects input to be a multiple of 16 - * Bytes. Only the last call before calling - * mbedtls_gcm_finish() can be less than 16 Bytes. - * - * \note For decryption, the output buffer cannot be the same as - * input buffer. If the buffers overlap, the output buffer - * must trail at least 8 Bytes behind the input buffer. - * - * \param ctx The GCM context. This must be initialized. - * \param length The length of the input data. This must be a multiple of - * 16 except in the last call before mbedtls_gcm_finish(). - * \param input The buffer holding the input data. If \p length is greater - * than zero, this must be a readable buffer of at least that - * size in Bytes. - * \param output The buffer for holding the output data. If \p length is - * greater than zero, this must be a writable buffer of at - * least that size in Bytes. - * - * \return \c 0 on success. - * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. - */ -int mbedtls_gcm_update( mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief This function finishes the GCM operation and generates - * the authentication tag. - * - * It wraps up the GCM stream, and generates the - * tag. The tag can have a maximum length of 16 Bytes. - * - * \param ctx The GCM context. This must be initialized. - * \param tag The buffer for holding the tag. This must be a readable - * buffer of at least \p tag_len Bytes. - * \param tag_len The length of the tag to generate. This must be at least - * four. - * - * \return \c 0 on success. - * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. - */ -int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, - unsigned char *tag, - size_t tag_len ); - -/** - * \brief This function clears a GCM context and the underlying - * cipher sub-context. - * - * \param ctx The GCM context to clear. If this is \c NULL, the call has - * no effect. Otherwise, this must be initialized. - */ -void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); - -/** - * \brief The GCM checkup routine. - * - * \return \c 0 on success. - * \return \c 1 on failure. - */ -int mbedtls_gcm_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - - -#endif /* gcm.h */ diff --git a/components/security/mbedtls/include/mbedtls/havege.h b/components/security/mbedtls/include/mbedtls/havege.h deleted file mode 100644 index dac5d311..00000000 --- a/components/security/mbedtls/include/mbedtls/havege.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * \file havege.h - * - * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - * - * 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) - */ -#ifndef MBEDTLS_HAVEGE_H -#define MBEDTLS_HAVEGE_H - -#include - -#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief HAVEGE state structure - */ -typedef struct -{ - int PT1, PT2, offset[2]; - int pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; - int WALK[8192]; -} -mbedtls_havege_state; - -/** - * \brief HAVEGE initialization - * - * \param hs HAVEGE state to be initialized - */ -void mbedtls_havege_init( mbedtls_havege_state *hs ); - -/** - * \brief Clear HAVEGE state - * - * \param hs HAVEGE state to be cleared - */ -void mbedtls_havege_free( mbedtls_havege_state *hs ); - -/** - * \brief HAVEGE rand function - * - * \param p_rng A HAVEGE state - * \param output Buffer to fill - * \param len Length of buffer - * - * \return 0 - */ -int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); - -#ifdef __cplusplus -} -#endif - -#endif /* havege.h */ diff --git a/components/security/mbedtls/include/mbedtls/hmac_drbg.h b/components/security/mbedtls/include/mbedtls/hmac_drbg.h deleted file mode 100644 index e0105580..00000000 --- a/components/security/mbedtls/include/mbedtls/hmac_drbg.h +++ /dev/null @@ -1,299 +0,0 @@ -/** - * \file hmac_drbg.h - * - * \brief HMAC_DRBG (NIST SP 800-90A) - * - * 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) - */ -#ifndef MBEDTLS_HMAC_DRBG_H -#define MBEDTLS_HMAC_DRBG_H - -#include "md.h" - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -/* - * Error codes - */ -#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ -#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ -#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ -#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) -#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -#endif - -#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) -#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -#endif - -#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) -#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -#endif - -#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) -#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ -#endif - -/* \} name SECTION: Module settings */ - -#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ -#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * HMAC_DRBG context. - */ -typedef struct -{ - /* Working state: the key K is not stored explicitely, - * but is implied by the HMAC context */ - mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ - unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ - int reseed_counter; /*!< reseed counter */ - - /* Administrative state */ - size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ - int prediction_resistance; /*!< enable prediction resistance (Automatic - reseed before every random generation) */ - int reseed_interval; /*!< reseed interval */ - - /* Callbacks */ - int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ - void *p_entropy; /*!< context for the entropy function */ - -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} mbedtls_hmac_drbg_context; - -/** - * \brief HMAC_DRBG context initialization - * Makes the context ready for mbedtls_hmac_drbg_seed(), - * mbedtls_hmac_drbg_seed_buf() or - * mbedtls_hmac_drbg_free(). - * - * \param ctx HMAC_DRBG context to be initialized - */ -void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); - -/** - * \brief HMAC_DRBG initial seeding - * Seed and setup entropy source for future reseeds. - * - * \param ctx HMAC_DRBG context to be seeded - * \param md_info MD algorithm to use for HMAC_DRBG - * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer - * length) - * \param p_entropy Entropy context - * \param custom Personalization data (Device specific identifiers) - * (Can be NULL) - * \param len Length of personalization data - * - * \note The "security strength" as defined by NIST is set to: - * 128 bits if md_alg is SHA-1, - * 192 bits if md_alg is SHA-224, - * 256 bits if md_alg is SHA-256 or higher. - * Note that SHA-256 is just as efficient as SHA-224. - * - * \return 0 if successful, or - * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or - * MBEDTLS_ERR_MD_ALLOC_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED. - */ -int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, - const mbedtls_md_info_t * md_info, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ); - -/** - * \brief Initilisation of simpified HMAC_DRBG (never reseeds). - * (For use with deterministic ECDSA.) - * - * \param ctx HMAC_DRBG context to be initialised - * \param md_info MD algorithm to use for HMAC_DRBG - * \param data Concatenation of entropy string and additional data - * \param data_len Length of data in bytes - * - * \return 0 if successful, or - * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or - * MBEDTLS_ERR_MD_ALLOC_FAILED. - */ -int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, - const mbedtls_md_info_t * md_info, - const unsigned char *data, size_t data_len ); - -/** - * \brief Enable / disable prediction resistance (Default: Off) - * - * Note: If enabled, entropy is used for ctx->entropy_len before each call! - * Only use this if you have ample supply of good entropy! - * - * \param ctx HMAC_DRBG context - * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF - */ -void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, - int resistance ); - -/** - * \brief Set the amount of entropy grabbed on each reseed - * (Default: given by the security strength, which - * depends on the hash used, see \c mbedtls_hmac_drbg_init() ) - * - * \param ctx HMAC_DRBG context - * \param len Amount of entropy to grab, in bytes - */ -void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, - size_t len ); - -/** - * \brief Set the reseed interval - * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) - * - * \param ctx HMAC_DRBG context - * \param interval Reseed interval - */ -void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, - int interval ); - -/** - * \brief HMAC_DRBG update state - * - * \param ctx HMAC_DRBG context - * \param additional Additional data to update state with, or NULL - * \param add_len Length of additional data, or 0 - * - * \note Additional data is optional, pass NULL and 0 as second - * third argument if no additional data is being used. - */ -void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); - -/** - * \brief HMAC_DRBG reseeding (extracts data from entropy source) - * - * \param ctx HMAC_DRBG context - * \param additional Additional data to add to state (Can be NULL) - * \param len Length of additional data - * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t len ); - -/** - * \brief HMAC_DRBG generate random with additional update input - * - * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. - * - * \param p_rng HMAC_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * \param additional Additional data to update with (can be NULL) - * \param add_len Length of additional data (can be 0) - * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or - * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG. - */ -int mbedtls_hmac_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, - size_t add_len ); - -/** - * \brief HMAC_DRBG generate random - * - * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. - * - * \param p_rng HMAC_DRBG context - * \param output Buffer to fill - * \param out_len Length of the buffer - * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG - */ -int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); - -/** - * \brief Free an HMAC_DRBG context - * - * \param ctx HMAC_DRBG context to free. - */ -void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Write a seed file - * - * \param ctx HMAC_DRBG context - * \param path Name of the file - * - * \return 0 if successful, 1 on file error, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); - -/** - * \brief Read and update a seed file. Seed is added to this - * instance - * - * \param ctx HMAC_DRBG context - * \param path Name of the file - * - * \return 0 if successful, 1 on file error, - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or - * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG - */ -int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); -#endif /* MBEDTLS_FS_IO */ - - -#if defined(MBEDTLS_SELF_TEST) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_hmac_drbg_self_test( int verbose ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* hmac_drbg.h */ diff --git a/components/security/mbedtls/include/mbedtls/mbedtls_ssl.h b/components/security/mbedtls/include/mbedtls/mbedtls_ssl.h deleted file mode 100644 index 29b7c72f..00000000 --- a/components/security/mbedtls/include/mbedtls/mbedtls_ssl.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2015-2017 Alibaba Group Holding Limited - */ - -#ifndef AOS_MBEDTLS_SSL_H -#define AOS_MBEDTLS_SSL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include "aos/kernel.h" - - -/** - * Create a ssl connect. - * - * @param[in] tcp_fd handle of the tcp socket. - * @param[in] ca_cert CA. - * @param[in] ca_cert_len length of the CA. - * - * @return NULL: error; ssl_param: success. - */ -void *mbedtls_ssl_connect(void *tcp_fd, const char *ca_cert, int ca_cert_len); - -/** - * Send data through ssl. - * - * @param[in] ssl handle of the ssl. - * @param[in] buffer data to send. - * @param[in] length length of the data. - * - * @return -1: error; others: length of the data be sended. - */ -int mbedtls_ssl_send(void *ssl, const char *buffer, int length); - -/** - * Recv data through ssl. - * - * @param[in] ssl handle of the ssl. - * @param[in] buffer buffer to recv data. - * @param[in] length the max size of the buffer. - * - * @return -1: error; 0: EOF; others: length of the data be sended. - */ -int mbedtls_ssl_recv(void *ssl, char *buffer, int length); - -/** - * Close the ssl. - * - * @param[in] ssl handle to be closed. - * - * @return 0: success. - */ -int mbedtls_ssl_close(void *ssl); - -#endif /* AOS_MBEDTLS_SSL_H */ - diff --git a/components/security/mbedtls/include/mbedtls/md.h b/components/security/mbedtls/include/mbedtls/md.h deleted file mode 100644 index 9b996a95..00000000 --- a/components/security/mbedtls/include/mbedtls/md.h +++ /dev/null @@ -1,354 +0,0 @@ -/** - * \file md.h - * - * \brief Generic message digest wrapper - * - * \author Adriaan de Jong - * - * 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) - */ -#ifndef MBEDTLS_MD_H -#define MBEDTLS_MD_H - -#include - -#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ -#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ -#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - MBEDTLS_MD_NONE=0, - MBEDTLS_MD_MD2, - MBEDTLS_MD_MD4, - MBEDTLS_MD_MD5, - MBEDTLS_MD_SHA1, - MBEDTLS_MD_SHA224, - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA384, - MBEDTLS_MD_SHA512, - MBEDTLS_MD_RIPEMD160, -} mbedtls_md_type_t; - -#if defined(MBEDTLS_SHA512_C) -#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ -#else -#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ -#endif - -/** - * Opaque struct defined in md_internal.h - */ -typedef struct mbedtls_md_info_t mbedtls_md_info_t; - -/** - * Generic message digest context. - */ -typedef struct { - /** Information about the associated message digest */ - const mbedtls_md_info_t *md_info; - - /** Digest-specific context */ - void *md_ctx; - - /** HMAC part of the context */ - void *hmac_ctx; -} mbedtls_md_context_t; - -/** - * \brief Returns the list of digests supported by the generic digest module. - * - * \return a statically allocated array of digests, the last entry - * is 0. - */ -const int *mbedtls_md_list( void ); - -/** - * \brief Returns the message digest information associated with the - * given digest name. - * - * \param md_name Name of the digest to search for. - * - * \return The message digest information associated with md_name or - * NULL if not found. - */ -const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); - -/** - * \brief Returns the message digest information associated with the - * given digest type. - * - * \param md_type type of digest to search for. - * - * \return The message digest information associated with md_type or - * NULL if not found. - */ -const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); - -/** - * \brief Initialize a md_context (as NONE) - * This should always be called first. - * Prepares the context for mbedtls_md_setup() or mbedtls_md_free(). - */ -void mbedtls_md_init( mbedtls_md_context_t *ctx ); - -/** - * \brief Free and clear the internal structures of ctx. - * Can be called at any time after mbedtls_md_init(). - * Mandatory once mbedtls_md_setup() has been called. - */ -void mbedtls_md_free( mbedtls_md_context_t *ctx ); - -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Select MD to use and allocate internal structures. - * Should be called after mbedtls_md_init() or mbedtls_md_free(). - * Makes it necessary to call mbedtls_md_free() later. - * - * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 - * - * \param ctx Context to set up. - * \param md_info Message digest to use. - * - * \returns \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, - * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. - */ -int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; -#undef MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -/** - * \brief Select MD to use and allocate internal structures. - * Should be called after mbedtls_md_init() or mbedtls_md_free(). - * Makes it necessary to call mbedtls_md_free() later. - * - * \param ctx Context to set up. - * \param md_info Message digest to use. - * \param hmac 0 to save some memory if HMAC will not be used, - * non-zero is HMAC is going to be used with this context. - * - * \returns \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, - * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. - */ -int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); - -/** - * \brief Clone the state of an MD context - * - * \note The two contexts must have been setup to the same type - * (cloning from SHA-256 to SHA-512 make no sense). - * - * \warning Only clones the MD state, not the HMAC state! (for now) - * - * \param dst The destination context - * \param src The context to be cloned - * - * \return \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. - */ -int mbedtls_md_clone( mbedtls_md_context_t *dst, - const mbedtls_md_context_t *src ); - -/** - * \brief Returns the size of the message digest output. - * - * \param md_info message digest info - * - * \return size of the message digest output in bytes. - */ -unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); - -/** - * \brief Returns the type of the message digest output. - * - * \param md_info message digest info - * - * \return type of the message digest output. - */ -mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); - -/** - * \brief Returns the name of the message digest output. - * - * \param md_info message digest info - * - * \return name of the message digest output. - */ -const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); - -/** - * \brief Prepare the context to digest a new message. - * Generally called after mbedtls_md_setup() or mbedtls_md_finish(). - * Followed by mbedtls_md_update(). - * - * \param ctx generic message digest context. - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_starts( mbedtls_md_context_t *ctx ); - -/** - * \brief Generic message digest process buffer - * Called between mbedtls_md_starts() and mbedtls_md_finish(). - * May be called repeatedly. - * - * \param ctx Generic message digest context - * \param input buffer holding the datal - * \param ilen length of the input data - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief Generic message digest final digest - * Called after mbedtls_md_update(). - * Usually followed by mbedtls_md_free() or mbedtls_md_starts(). - * - * \param ctx Generic message digest context - * \param output Generic message digest checksum result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); - -/** - * \brief Output = message_digest( input buffer ) - * - * \param md_info message digest info - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic message digest checksum result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, - unsigned char *output ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Output = message_digest( file contents ) - * - * \param md_info message digest info - * \param path input file name - * \param output generic message digest checksum result - * - * \return 0 if successful, - * MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, - * MBEDTLS_ERR_MD_BAD_INPUT_DATA if md_info was NULL. - */ -int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, - unsigned char *output ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Set HMAC key and prepare to authenticate a new message. - * Usually called after mbedtls_md_setup() or mbedtls_md_hmac_finish(). - * - * \param ctx HMAC context - * \param key HMAC secret key - * \param keylen length of the HMAC key in bytes - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, - size_t keylen ); - -/** - * \brief Generic HMAC process buffer. - * Called between mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() - * and mbedtls_md_hmac_finish(). - * May be called repeatedly. - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief Output HMAC. - * Called after mbedtls_md_hmac_update(). - * Usually followed by mbedtls_md_hmac_reset(), - * mbedtls_md_hmac_starts(), or mbedtls_md_free(). - * - * \param ctx HMAC context - * \param output Generic HMAC checksum result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); - -/** - * \brief Prepare to authenticate a new message with the same key. - * Called after mbedtls_md_hmac_finish() and before - * mbedtls_md_hmac_update(). - * - * \param ctx HMAC context to be reset - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); - -/** - * \brief Output = Generic_HMAC( hmac key, input buffer ) - * - * \param md_info message digest info - * \param key HMAC secret key - * \param keylen length of the HMAC key in bytes - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic HMAC-result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ); - -/* Internal use */ -int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_MD_H */ diff --git a/components/security/mbedtls/include/mbedtls/md2.h b/components/security/mbedtls/include/mbedtls/md2.h deleted file mode 100644 index 0f93fbf4..00000000 --- a/components/security/mbedtls/include/mbedtls/md2.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * \file md2.h - * - * \brief MD2 message digest algorithm (hash function) - * - * 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) - */ -#ifndef MBEDTLS_MD2_H -#define MBEDTLS_MD2_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if !defined(MBEDTLS_MD2_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD2 context structure - */ -typedef struct -{ - unsigned char cksum[16]; /*!< checksum of the data block */ - unsigned char state[48]; /*!< intermediate digest state */ - unsigned char buffer[16]; /*!< data block being processed */ - size_t left; /*!< amount of data in buffer */ -} -mbedtls_md2_context; - -/** - * \brief Initialize MD2 context - * - * \param ctx MD2 context to be initialized - */ -void mbedtls_md2_init( mbedtls_md2_context *ctx ); - -/** - * \brief Clear MD2 context - * - * \param ctx MD2 context to be cleared - */ -void mbedtls_md2_free( mbedtls_md2_context *ctx ); - -/** - * \brief Clone (the state of) an MD2 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_md2_clone( mbedtls_md2_context *dst, - const mbedtls_md2_context *src ); - -/** - * \brief MD2 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_md2_starts( mbedtls_md2_context *ctx ); - -/** - * \brief MD2 process buffer - * - * \param ctx MD2 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD2 final digest - * - * \param ctx MD2 context - * \param output MD2 checksum result - */ -void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_MD2_ALT */ -#include "md2_alt.h" -#endif /* MBEDTLS_MD2_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = MD2( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD2 checksum result - */ -void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_md2_self_test( int verbose ); - -/* Internal use */ -void mbedtls_md2_process( mbedtls_md2_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_md2.h */ diff --git a/components/security/mbedtls/include/mbedtls/md5.h b/components/security/mbedtls/include/mbedtls/md5.h deleted file mode 100644 index b37637fa..00000000 --- a/components/security/mbedtls/include/mbedtls/md5.h +++ /dev/null @@ -1,137 +0,0 @@ -/** - * \file md5.h - * - * \brief MD5 message digest algorithm (hash function) - * - * 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) - */ -#ifndef MBEDTLS_MD5_H -#define MBEDTLS_MD5_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_MD5_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD5 context structure - */ -typedef struct { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -mbedtls_md5_context; - -/** - * \brief Initialize MD5 context - * - * \param ctx MD5 context to be initialized - */ -void mbedtls_md5_init( mbedtls_md5_context *ctx ); - -/** - * \brief Clear MD5 context - * - * \param ctx MD5 context to be cleared - */ -void mbedtls_md5_free( mbedtls_md5_context *ctx ); - -/** - * \brief Clone (the state of) an MD5 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_md5_clone( mbedtls_md5_context *dst, - const mbedtls_md5_context *src ); - -/** - * \brief MD5 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_md5_starts( mbedtls_md5_context *ctx ); - -/** - * \brief MD5 process buffer - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD5 final digest - * - * \param ctx MD5 context - * \param output MD5 checksum result - */ -void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ); - -/* Internal use */ -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_MD5_ALT */ -#include "md5_alt.h" -#endif /* MBEDTLS_MD5_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_MD5_ALT) -/** - * \brief Output = MD5( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD5 checksum result - */ -void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); -#endif /* MBEDTLS_MD5_ALT */ - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_md5_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_md5.h */ diff --git a/components/security/mbedtls/include/mbedtls/md5_alt.h b/components/security/mbedtls/include/mbedtls/md5_alt.h deleted file mode 100644 index c3b646d3..00000000 --- a/components/security/mbedtls/include/mbedtls/md5_alt.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2018 The YunOS IoT Project. All rights reserved. - */ - -#ifndef MBEDTLS_MD5_ALT_H -#define MBEDTLS_MD5_ALT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - size_t size; - void *ali_ctx; -} mbedtls_md5_context; - -void mbedtls_md5_init_alt(mbedtls_md5_context *ctx); -void mbedtls_md5_free_alt(mbedtls_md5_context *ctx); - -void mbedtls_md5_clone_alt(mbedtls_md5_context *dst, - const mbedtls_md5_context *src); - -void mbedtls_md5_starts_alt(mbedtls_md5_context *ctx); -void mbedtls_md5_update_alt(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen); -void mbedtls_md5_finish_alt(mbedtls_md5_context *ctx, unsigned char output[16]); - -void mbedtls_md5_alt( const unsigned char *input, size_t ilen, unsigned char output[16] ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_MD5_ALT_H */ diff --git a/components/security/mbedtls/include/mbedtls/md_internal.h b/components/security/mbedtls/include/mbedtls/md_internal.h deleted file mode 100644 index e2441bbc..00000000 --- a/components/security/mbedtls/include/mbedtls/md_internal.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * \file md_internal.h - * - * \brief Message digest wrappers. - * - * \warning This in an internal header. Do not include directly. - * - * \author Adriaan de Jong - * - * 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) - */ -#ifndef MBEDTLS_MD_WRAP_H -#define MBEDTLS_MD_WRAP_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "md.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Message digest information. - * Allows message digest functions to be called in a generic way. - */ -struct mbedtls_md_info_t -{ - /** Digest identifier */ - mbedtls_md_type_t type; - - /** Name of the message digest */ - const char * name; - - /** Output length of the digest function in bytes */ - int size; - - /** Block length of the digest function in bytes */ - int block_size; - - /** Digest initialisation function */ - void (*starts_func)( void *ctx ); - - /** Digest update function */ - void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); - - /** Digest finalisation function */ - void (*finish_func)( void *ctx, unsigned char *output ); - - /** Generic digest function */ - void (*digest_func)( const unsigned char *input, size_t ilen, - unsigned char *output ); - - /** Allocate a new context */ - void * (*ctx_alloc_func)( void ); - - /** Free the given context */ - void (*ctx_free_func)( void *ctx ); - - /** Clone state from a context */ - void (*clone_func)( void *dst, const void *src ); - - /** Internal use only */ - void (*process_func)( void *ctx, const unsigned char *input ); -}; - -#if defined(MBEDTLS_MD2_C) -extern const mbedtls_md_info_t mbedtls_md2_info; -#endif -#if defined(MBEDTLS_MD4_C) -extern const mbedtls_md_info_t mbedtls_md4_info; -#endif -#if defined(MBEDTLS_MD5_C) -extern const mbedtls_md_info_t mbedtls_md5_info; -#endif -#if defined(MBEDTLS_RIPEMD160_C) -extern const mbedtls_md_info_t mbedtls_ripemd160_info; -#endif -#if defined(MBEDTLS_SHA1_C) -extern const mbedtls_md_info_t mbedtls_sha1_info; -#endif -#if defined(MBEDTLS_SHA256_C) -extern const mbedtls_md_info_t mbedtls_sha224_info; -extern const mbedtls_md_info_t mbedtls_sha256_info; -#endif -#if defined(MBEDTLS_SHA512_C) -extern const mbedtls_md_info_t mbedtls_sha384_info; -extern const mbedtls_md_info_t mbedtls_sha512_info; -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/components/security/mbedtls/include/mbedtls/mycalloc.h b/components/security/mbedtls/include/mbedtls/mycalloc.h deleted file mode 100644 index 30df01f7..00000000 --- a/components/security/mbedtls/include/mbedtls/mycalloc.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef MBEDTLS_MYCALLOC_H -#define MBEDTLS_MYCALLOC_H -#include -void *mycalloc(size_t numitems, size_t size); -#endif \ No newline at end of file diff --git a/components/security/mbedtls/include/mbedtls/net.h b/components/security/mbedtls/include/mbedtls/net.h deleted file mode 100644 index 774559b3..00000000 --- a/components/security/mbedtls/include/mbedtls/net.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * \file net.h - * - * \brief Deprecated header file that includes mbedtls/net_sockets.h - * - * Copyright (C) 2006-2016, 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) - * - * \deprecated Superseded by mbedtls/net_sockets.h - */ - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#include "mbedtls/net_sockets.h" -#if defined(MBEDTLS_DEPRECATED_WARNING) -#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" -#endif /* MBEDTLS_DEPRECATED_WARNING */ -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/components/security/mbedtls/include/mbedtls/net_sockets.h b/components/security/mbedtls/include/mbedtls/net_sockets.h deleted file mode 100644 index de335526..00000000 --- a/components/security/mbedtls/include/mbedtls/net_sockets.h +++ /dev/null @@ -1,225 +0,0 @@ -/** - * \file net_sockets.h - * - * \brief Network communication 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) - */ -#ifndef MBEDTLS_NET_SOCKETS_H -#define MBEDTLS_NET_SOCKETS_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "ssl.h" - -#include -#include - -#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ -#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ -#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ -#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ -#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ -#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ -#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ -#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ -#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ -#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ -#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ - -#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ - -#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ -#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Wrapper type for sockets. - * - * Currently backed by just a file descriptor, but might be more in the future - * (eg two file descriptors for combined IPv4 + IPv6 support, or additional - * structures for hand-made UDP demultiplexing). - */ -typedef struct -{ - int fd; /**< The underlying file descriptor */ -} -mbedtls_net_context; - -/** - * \brief Initialize a context - * Just makes the context ready to be used or freed safely. - * - * \param ctx Context to initialize - */ -void mbedtls_net_init( mbedtls_net_context *ctx ); - -/** - * \brief Initiate a connection with host:port in the given protocol - * - * \param ctx Socket to use - * \param host Host to connect to - * \param port Port to connect to - * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP - * - * \return 0 if successful, or one of: - * MBEDTLS_ERR_NET_SOCKET_FAILED, - * MBEDTLS_ERR_NET_UNKNOWN_HOST, - * MBEDTLS_ERR_NET_CONNECT_FAILED - * - * \note Sets the socket in connected mode even with UDP. - */ -int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); - -/** - * \brief Create a receiving socket on bind_ip:port in the chosen - * protocol. If bind_ip == NULL, all interfaces are bound. - * - * \param ctx Socket to use - * \param bind_ip IP to bind to, can be NULL - * \param port Port number to use - * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP - * - * \return 0 if successful, or one of: - * MBEDTLS_ERR_NET_SOCKET_FAILED, - * MBEDTLS_ERR_NET_BIND_FAILED, - * MBEDTLS_ERR_NET_LISTEN_FAILED - * - * \note Regardless of the protocol, opens the sockets and binds it. - * In addition, make the socket listening if protocol is TCP. - */ -int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); - -/** - * \brief Accept a connection from a remote client - * - * \param bind_ctx Relevant socket - * \param client_ctx Will contain the connected client socket - * \param client_ip Will contain the client IP address - * \param buf_size Size of the client_ip buffer - * \param ip_len Will receive the size of the client IP written - * - * \return 0 if successful, or - * MBEDTLS_ERR_NET_ACCEPT_FAILED, or - * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, - * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to - * non-blocking and accept() would block. - */ -int mbedtls_net_accept( mbedtls_net_context *bind_ctx, - mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len ); - -/** - * \brief Set the socket blocking - * - * \param ctx Socket to set - * - * \return 0 if successful, or a non-zero error code - */ -int mbedtls_net_set_block( mbedtls_net_context *ctx ); - -/** - * \brief Set the socket non-blocking - * - * \param ctx Socket to set - * - * \return 0 if successful, or a non-zero error code - */ -int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); - -/** - * \brief Portable usleep helper - * - * \param usec Amount of microseconds to sleep - * - * \note Real amount of time slept will not be less than - * select()'s timeout granularity (typically, 10ms). - */ -void mbedtls_net_usleep( unsigned long usec ); - -/** - * \brief Read at most 'len' characters. If no error occurs, - * the actual amount read is returned. - * - * \param ctx Socket - * \param buf The buffer to write to - * \param len Maximum length of the buffer - * - * \return the number of bytes received, - * or a non-zero error code; with a non-blocking socket, - * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. - */ -int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); - -/** - * \brief Write at most 'len' characters. If no error occurs, - * the actual amount read is returned. - * - * \param ctx Socket - * \param buf The buffer to read from - * \param len The length of the buffer - * - * \return the number of bytes sent, - * or a non-zero error code; with a non-blocking socket, - * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. - */ -int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); - -/** - * \brief Read at most 'len' characters, blocking for at most - * 'timeout' seconds. If no error occurs, the actual amount - * read is returned. - * - * \param ctx Socket - * \param buf The buffer to write to - * \param len Maximum length of the buffer - * \param timeout Maximum number of milliseconds to wait for data - * 0 means no timeout (wait forever) - * - * \return the number of bytes received, - * or a non-zero error code: - * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, - * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. - * - * \note This function will block (until data becomes available or - * timeout is reached) even if the socket is set to - * non-blocking. Handling timeouts with non-blocking reads - * requires a different strategy. - */ -int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ); - -/** - * \brief Gracefully shutdown the connection and free associated data - * - * \param ctx The context to free - */ -void mbedtls_net_free( mbedtls_net_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* net_sockets.h */ diff --git a/components/security/mbedtls/include/mbedtls/oid.h b/components/security/mbedtls/include/mbedtls/oid.h deleted file mode 100644 index fcecdafd..00000000 --- a/components/security/mbedtls/include/mbedtls/oid.h +++ /dev/null @@ -1,570 +0,0 @@ -/** - * \file oid.h - * - * \brief Object Identifier (OID) database - * - * 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) - */ -#ifndef MBEDTLS_OID_H -#define MBEDTLS_OID_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "asn1.h" -#include "pk.h" - -#include - -#if defined(MBEDTLS_CIPHER_C) -#include "cipher.h" -#endif - -#if defined(MBEDTLS_MD_C) -#include "md.h" -#endif - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -#include "x509.h" -#endif - -#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ -#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ - -/* - * Top level OID tuples - */ -#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ -#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ -#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ -#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ - -/* - * ISO Member bodies OID parts - */ -#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ -#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ -#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ -#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ -#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_ANSI_X9_62 - -/* - * ISO Identified organization OID parts - */ -#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ -#define MBEDTLS_OID_ORG_OIW "\x0e" -#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" -#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" -#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" -#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ -#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM -#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ -#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST - -/* - * ISO ITU OID parts - */ -#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ -#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ - -#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ -#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ - -#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ -#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ - -/* ISO arc for standard certificate and CRL extensions */ -#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ - -/** - * Private Internet Extensions - * { iso(1) identified-organization(3) dod(6) internet(1) - * security(5) mechanisms(5) pkix(7) } - */ -#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" - -/* - * Arc for standard naming attributes - */ -#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ -#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ -#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ -#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ -#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ -#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ -#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ -#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ -#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ -#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ -#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ -#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ -#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ -#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ -#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ -#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ -#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ -#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ - -#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ - -/* - * OIDs for standard certificate extensions - */ -#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ -#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ -#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ -#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ -#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ -#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ -#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ -#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ -#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ -#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ -#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ -#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ -#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ -#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ -#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ - -/* - * Netscape certificate extensions - */ -#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" -#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" -#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" -#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" -#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" -#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" -#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" -#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" -#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" -#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" -#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" - -/* - * OIDs for CRL extensions - */ -#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" -#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ - -/* - * X.509 v3 Extended key usage OIDs - */ -#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ - -#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ -#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ -#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ -#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ -#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ -#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ -#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ - -/* - * PKCS definition OIDs - */ - -#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ -#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ -#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ -#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ -#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ - -/* - * PKCS#1 OIDs - */ -#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ -#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ -#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ -#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ -#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ -#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ -#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ -#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ -#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ - -#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" - -#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ - -/* RFC 4055 */ -#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ -#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ - -/* - * Digest algorithms - */ -#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ -#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ - -#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ - -/* - * Encryption algorithms - */ -#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ -#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ - -/* - * PKCS#5 OIDs - */ -#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ -#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ -#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ - -/* - * PKCS#5 PBES1 algorithms - */ -#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ -#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ -#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ -#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ -#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ -#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ - -/* - * PKCS#8 OIDs - */ -#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ - -/* - * PKCS#12 PBE OIDs - */ -#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ - -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ - -/* - * EC key algorithms from RFC 5480 - */ - -/* id-ecPublicKey OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ -#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" - -/* id-ecDH OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) - * schemes(1) ecdh(12) } */ -#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" - -/* - * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 - */ - -/* secp192r1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ -#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" - -/* secp224r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ -#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" - -/* secp256r1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ -#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" - -/* secp384r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ -#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" - -/* secp521r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ -#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" - -/* secp192k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ -#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" - -/* secp224k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ -#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" - -/* secp256k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ -#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" - -/* RFC 5639 4.1 - * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) - * identified-organization(3) teletrust(36) algorithm(3) signature- - * algorithm(3) ecSign(2) 8} - * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} - * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ -#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" - -/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ -#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" - -/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ -#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" - -/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ -#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" - -/* - * SEC1 C.1 - * - * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } - * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} - */ -#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" -#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" - -/* - * ECDSA signature identifiers, from RFC 5480 - */ -#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ -#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ - -/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ -#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" - -/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 1 } */ -#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" - -/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 2 } */ -#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" - -/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 3 } */ -#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" - -/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 4 } */ -#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Base OID descriptor structure - */ -typedef struct { - const char *asn1; /*!< OID ASN.1 representation */ - size_t asn1_len; /*!< length of asn1 */ - const char *name; /*!< official name (e.g. from RFC) */ - const char *description; /*!< human friendly description */ -} mbedtls_oid_descriptor_t; - -/** - * \brief Translate an ASN.1 OID into its numeric representation - * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") - * - * \param buf buffer to put representation in - * \param size size of the buffer - * \param oid OID to translate - * - * \return Length of the string written (excluding final NULL) or - * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error - */ -int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -/** - * \brief Translate an X.509 extension OID into local values - * - * \param oid OID to use - * \param ext_type place to store the extension type - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); -#endif - -/** - * \brief Translate an X.509 attribute type OID into the short name - * (e.g. the OID for an X520 Common Name into "CN") - * - * \param oid OID to use - * \param short_name place to store the string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); - -/** - * \brief Translate PublicKeyAlgorithm OID into pk_type - * - * \param oid OID to use - * \param pk_alg place to store public key algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); - -/** - * \brief Translate pk_type into PublicKeyAlgorithm OID - * - * \param pk_alg Public key type to look for - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, - const char **oid, size_t *olen ); - -#if defined(MBEDTLS_ECP_C) -/** - * \brief Translate NamedCurve OID into an EC group identifier - * - * \param oid OID to use - * \param grp_id place to store group id - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); - -/** - * \brief Translate EC group identifier into NamedCurve OID - * - * \param grp_id EC group identifier - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, - const char **oid, size_t *olen ); -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_MD_C) -/** - * \brief Translate SignatureAlgorithm OID into md_type and pk_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * \param pk_alg place to store public key algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); - -/** - * \brief Translate SignatureAlgorithm OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); - -/** - * \brief Translate md_type and pk_type into SignatureAlgorithm OID - * - * \param md_alg message digest algorithm - * \param pk_alg public key algorithm - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const char **oid, size_t *olen ); - -/** - * \brief Translate hash algorithm OID into md_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); -#endif /* MBEDTLS_MD_C */ - -/** - * \brief Translate Extended Key Usage OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); - -/** - * \brief Translate md_type into hash algorithm OID - * - * \param md_alg message digest algorithm - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); - -#if defined(MBEDTLS_CIPHER_C) -/** - * \brief Translate encryption algorithm OID into cipher_type - * - * \param oid OID to use - * \param cipher_alg place to store cipher algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_PKCS12_C) -/** - * \brief Translate PKCS#12 PBE algorithm OID into md_type and - * cipher_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * \param cipher_alg place to store cipher algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, - mbedtls_cipher_type_t *cipher_alg ); -#endif /* MBEDTLS_PKCS12_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* oid.h */ diff --git a/components/security/mbedtls/include/mbedtls/padlock.h b/components/security/mbedtls/include/mbedtls/padlock.h deleted file mode 100644 index 2045a5ab..00000000 --- a/components/security/mbedtls/include/mbedtls/padlock.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - * \file padlock.h - * - * \brief VIA PadLock ACE for HW encryption/decryption supported by some - * processors - * - * 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) - */ -#ifndef MBEDTLS_PADLOCK_H -#define MBEDTLS_PADLOCK_H - -#include "aes.h" - -#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ - -#if defined(__has_feature) -#if __has_feature(address_sanitizer) -#define MBEDTLS_HAVE_ASAN -#endif -#endif - -/* Some versions of ASan result in errors about not enough registers */ -#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ - !defined(MBEDTLS_HAVE_ASAN) - -#ifndef MBEDTLS_HAVE_X86 -#define MBEDTLS_HAVE_X86 -#endif - -#include - -#define MBEDTLS_PADLOCK_RNG 0x000C -#define MBEDTLS_PADLOCK_ACE 0x00C0 -#define MBEDTLS_PADLOCK_PHE 0x0C00 -#define MBEDTLS_PADLOCK_PMM 0x3000 - -#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15)) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PadLock detection routine - * - * \param feature The feature to detect - * - * \return 1 if CPU has support for the feature, 0 otherwise - */ -int mbedtls_padlock_has_support( int feature ); - -/** - * \brief PadLock AES-ECB block en(de)cryption - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if success, 1 if operation failed - */ -int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief PadLock AES-CBC buffer en(de)cryption - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if success, 1 if operation failed - */ -int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -#ifdef __cplusplus -} -#endif - -#endif /* HAVE_X86 */ - -#endif /* padlock.h */ diff --git a/components/security/mbedtls/include/mbedtls/pem.h b/components/security/mbedtls/include/mbedtls/pem.h deleted file mode 100644 index 54dc02d7..00000000 --- a/components/security/mbedtls/include/mbedtls/pem.h +++ /dev/null @@ -1,129 +0,0 @@ -/** - * \file pem.h - * - * \brief Privacy Enhanced Mail (PEM) decoding - * - * 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) - */ -#ifndef MBEDTLS_PEM_H -#define MBEDTLS_PEM_H - -#include - -/** - * \name PEM Error codes - * These error codes are returned in case of errors reading the - * PEM data. - * \{ - */ -#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ -#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ -#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ -#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ -#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ -#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ -#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ -#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ -#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ -/* \} name */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) -/** - * \brief PEM context structure - */ -typedef struct -{ - unsigned char *buf; /*!< buffer for decoded data */ - size_t buflen; /*!< length of the buffer */ - unsigned char *info; /*!< buffer for extra header information */ -} -mbedtls_pem_context; - -/** - * \brief PEM context setup - * - * \param ctx context to be initialized - */ -void mbedtls_pem_init( mbedtls_pem_context *ctx ); - -/** - * \brief Read a buffer for PEM information and store the resulting - * data into the specified context buffers. - * - * \param ctx context to use - * \param header header string to seek and expect - * \param footer footer string to seek and expect - * \param data source data to look in (must be nul-terminated) - * \param pwd password for decryption (can be NULL) - * \param pwdlen length of password - * \param use_len destination for total length used (set after header is - * correctly read, so unless you get - * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or - * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is - * the length to skip) - * - * \note Attempts to check password correctness by verifying if - * the decrypted text starts with an ASN.1 sequence of - * appropriate length - * - * \return 0 on success, or a specific PEM error code - */ -int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, - const unsigned char *data, - const unsigned char *pwd, - size_t pwdlen, size_t *use_len ); - -/** - * \brief PEM context memory freeing - * - * \param ctx context to be freed - */ -void mbedtls_pem_free( mbedtls_pem_context *ctx ); -#endif /* MBEDTLS_PEM_PARSE_C */ - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a buffer of PEM information from a DER encoded - * buffer. - * - * \param header header string to write - * \param footer footer string to write - * \param der_data DER data to write - * \param der_len length of the DER data - * \param buf buffer to write to - * \param buf_len length of output buffer - * \param olen total length written / required (if buf_len is not enough) - * - * \return 0 on success, or a specific PEM or BASE64 error code. On - * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required - * size. - */ -int mbedtls_pem_write_buffer( const char *header, const char *footer, - const unsigned char *der_data, size_t der_len, - unsigned char *buf, size_t buf_len, size_t *olen ); -#endif /* MBEDTLS_PEM_WRITE_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* pem.h */ diff --git a/components/security/mbedtls/include/mbedtls/pk.h b/components/security/mbedtls/include/mbedtls/pk.h deleted file mode 100644 index 5c0637b6..00000000 --- a/components/security/mbedtls/include/mbedtls/pk.h +++ /dev/null @@ -1,620 +0,0 @@ -/** - * \file pk.h - * - * \brief Public Key abstraction layer - * - * 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) - */ - -#ifndef MBEDTLS_PK_H -#define MBEDTLS_PK_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "md.h" - -#if defined(MBEDTLS_RSA_C) -#include "rsa.h" -#endif - -#if defined(MBEDTLS_ECP_C) -#include "ecp.h" -#endif - -#if defined(MBEDTLS_ECDSA_C) -#include "ecdsa.h" -#endif - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ -#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ -#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ -#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ -#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ -#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ -#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ -#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ -#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ -#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ -#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ -#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ -#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The signature is valid but its length is less than expected. */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_IOT_SPECIFIC) -#define CRT_OID_IDENT_LEN 0x09 -#endif - -/** - * \brief Public key types - */ -typedef enum { - MBEDTLS_PK_NONE=0, - MBEDTLS_PK_RSA, - MBEDTLS_PK_ECKEY, - MBEDTLS_PK_ECKEY_DH, - MBEDTLS_PK_ECDSA, - MBEDTLS_PK_RSA_ALT, - MBEDTLS_PK_RSASSA_PSS, -} mbedtls_pk_type_t; - -/** - * \brief Options for RSASSA-PSS signature verification. - * See \c mbedtls_rsa_rsassa_pss_verify_ext() - */ -typedef struct -{ - mbedtls_md_type_t mgf1_hash_id; - int expected_salt_len; - -} mbedtls_pk_rsassa_pss_options; - -/** - * \brief Types for interfacing with the debug module - */ -typedef enum -{ - MBEDTLS_PK_DEBUG_NONE = 0, - MBEDTLS_PK_DEBUG_MPI, - MBEDTLS_PK_DEBUG_ECP, -} mbedtls_pk_debug_type; - -/** - * \brief Item to send to the debug module - */ -typedef struct -{ - mbedtls_pk_debug_type type; - const char *name; - void *value; -} mbedtls_pk_debug_item; - -/** Maximum number of item send for debugging, plus 1 */ -#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 - -/** - * \brief Public key information and operations - */ -typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; - -/** - * \brief Public key container - */ -typedef struct -{ - const mbedtls_pk_info_t * pk_info; /**< Public key informations */ - void * pk_ctx; /**< Underlying public key context */ -} mbedtls_pk_context; - -#if defined(MBEDTLS_RSA_C) -/** - * Quick access to an RSA context inside a PK context. - * - * \warning You must make sure the PK context actually holds an RSA context - * before using this function! - */ -static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) -{ - return( (mbedtls_rsa_context *) (pk).pk_ctx ); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/** - * Quick access to an EC context inside a PK context. - * - * \warning You must make sure the PK context actually holds an EC context - * before using this function! - */ -static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) -{ - return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/** - * \brief Types for RSA-alt abstraction - */ -typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, - const unsigned char *input, unsigned char *output, - size_t output_max_len ); -typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, - const unsigned char *hash, unsigned char *sig ); -typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/** - * \brief Return information associated with the given PK type - * - * \param pk_type PK type to search for. - * - * \return The PK info associated with the type or NULL if not found. - */ -const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); - -/** - * \brief Initialize a mbedtls_pk_context (as NONE) - */ -void mbedtls_pk_init( mbedtls_pk_context *ctx ); - -/** - * \brief Free a mbedtls_pk_context - */ -void mbedtls_pk_free( mbedtls_pk_context *ctx ); - -/** - * \brief Initialize a PK context with the information given - * and allocates the type-specific PK subcontext. - * - * \param ctx Context to initialize. Must be empty (type NONE). - * \param info Information to use - * - * \return 0 on success, - * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, - * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. - * - * \note For contexts holding an RSA-alt key, use - * \c mbedtls_pk_setup_rsa_alt() instead. - */ -int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/** - * \brief Initialize an RSA-alt context - * - * \param ctx Context to initialize. Must be empty (type NONE). - * \param key RSA key pointer - * \param decrypt_func Decryption function - * \param sign_func Signing function - * \param key_len_func Function returning key length in bytes - * - * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the - * context wasn't already initialized as RSA_ALT. - * - * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. - */ -int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func ); -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/** - * \brief Get the size in bits of the underlying key - * - * \param ctx Context to use - * - * \return Key size in bits, or 0 on error - */ -size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); - -/** - * \brief Get the length in bytes of the underlying key - * \param ctx Context to use - * - * \return Key length in bytes, or 0 on error - */ -static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) -{ - return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); -} - -/** - * \brief Tell if a context can do the operation given by type - * - * \param ctx Context to test - * \param type Target type - * - * \return 0 if context can't do the operations, - * 1 otherwise. - */ -int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); - -/** - * \brief Verify signature (including padding if relevant). - * - * \param ctx PK context to use - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * - * \return 0 on success (signature is valid), - * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than sig_len, - * or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) - * to verify RSASSA_PSS signatures. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 - */ -int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); - -/** - * \brief Verify signature, with options. - * (Includes verification of the padding depending on type.) - * - * \param type Signature type (inc. possible padding type) to verify - * \param options Pointer to type-specific options, or NULL - * \param ctx PK context to use - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * - * \return 0 on success (signature is valid), - * MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be - * used for this type of signatures, - * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than sig_len, - * or a specific error code. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 - * - * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point - * to a mbedtls_pk_rsassa_pss_options structure, - * otherwise it must be NULL. - */ -int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); - -/** - * \brief Make signature, including padding if relevant. - * - * \param ctx PK context to use - must hold a private key - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Place to write the signature - * \param sig_len Number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 on success, or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * There is no interface in the PK module to make RSASSA-PSS - * signatures yet. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. - * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. - */ -int mbedtls_pk_sign( mbedtls_pk_context *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 ); - -/** - * \brief Decrypt message (including padding if relevant). - * - * \param ctx PK context to use - must hold a private key - * \param input Input to decrypt - * \param ilen Input size - * \param output Decrypted output - * \param olen Decrypted message length - * \param osize Size of the output buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_pk_decrypt( mbedtls_pk_context *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 ); - -/** - * \brief Encrypt message (including padding if relevant). - * - * \param ctx PK context to use - * \param input Message to encrypt - * \param ilen Message size - * \param output Encrypted output - * \param olen Encrypted output length - * \param osize Size of the output buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_pk_encrypt( mbedtls_pk_context *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 ); - -/** - * \brief Check if a public-private pair of keys matches. - * - * \param pub Context holding a public key. - * \param prv Context holding a private (and public) key. - * - * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA - */ -int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); - -/** - * \brief Export debug information - * - * \param ctx Context to use - * \param items Place to write debug items - * - * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA - */ -int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); - -/** - * \brief Access the type name - * - * \param ctx Context to use - * - * \return Type name on success, or "invalid PK" - */ -const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); - -/** - * \brief Get the key type - * - * \param ctx Context to use - * - * \return Type on success, or MBEDTLS_PK_NONE - */ -mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); - -#if defined(MBEDTLS_PK_PARSE_C) -/** \ingroup pk_module */ -/** - * \brief Parse a private key in PEM or DER format - * - * \param ctx key to be initialized - * \param key input buffer - * \param keylen size of the buffer - * (including the terminating null byte for PEM data) - * \param pwd password for decryption (optional) - * \param pwdlen size of the password - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ); - -/** \ingroup pk_module */ -/** - * \brief Parse a public key in PEM or DER format - * - * \param ctx key to be initialized - * \param key input buffer - * \param keylen size of the buffer - * (including the terminating null byte for PEM data) - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen ); - -#if defined(MBEDTLS_FS_IO) -/** \ingroup pk_module */ -/** - * \brief Load and parse a private key - * - * \param ctx key to be initialized - * \param path filename to read the private key from - * \param password password to decrypt the file (can be NULL) - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, - const char *path, const char *password ); - -/** \ingroup pk_module */ -/** - * \brief Load and parse a public key - * - * \param ctx key to be initialized - * \param path filename to read the public key from - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If - * you need a specific key type, check the result with - * mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); -#endif /* MBEDTLS_FS_IO */ -#endif /* MBEDTLS_PK_PARSE_C */ - -#if defined(MBEDTLS_PK_WRITE_C) -/** - * \brief Write a private key to a PKCS#1 or SEC1 DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx private to write away - * \param buf buffer to write to - * \param size size of the buffer - * - * \return length of data written if successful, or a specific - * error code - */ -int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - -/** - * \brief Write a public key to a SubjectPublicKeyInfo DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx public key to write away - * \param buf buffer to write to - * \param size size of the buffer - * - * \return length of data written if successful, or a specific - * error code - */ -int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a public key to a PEM string - * - * \param ctx public key to write away - * \param buf buffer to write to - * \param size size of the buffer - * - * \return 0 if successful, or a specific error code - */ -int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - -/** - * \brief Write a private key to a PKCS#1 or SEC1 PEM string - * - * \param ctx private to write away - * \param buf buffer to write to - * \param size size of the buffer - * - * \return 0 if successful, or a specific error code - */ -int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_PK_WRITE_C */ - -/* - * WARNING: Low-level functions. You probably do not want to use these unless - * you are certain you do ;) - */ - -#if defined(MBEDTLS_PK_PARSE_C) -/** - * \brief Parse a SubjectPublicKeyInfo DER structure - * - * \param p the position in the ASN.1 data - * \param end end of the buffer - * \param pk the key to fill - * - * \return 0 if successful, or a specific PK error code - */ -int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk ); -#endif /* MBEDTLS_PK_PARSE_C */ - -#if defined(MBEDTLS_PK_WRITE_C) -/** - * \brief Write a subjectPublicKey to ASN.1 data - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param key public key to write away - * - * \return the length written or a negative error code - */ -int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key ); -#endif /* MBEDTLS_PK_WRITE_C */ - -/* - * Internal module functions. You probably do not want to use these unless you - * know you do. - */ -#if defined(MBEDTLS_FS_IO) -int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PK_H */ diff --git a/components/security/mbedtls/include/mbedtls/pk_internal.h b/components/security/mbedtls/include/mbedtls/pk_internal.h deleted file mode 100644 index 01d0f214..00000000 --- a/components/security/mbedtls/include/mbedtls/pk_internal.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * \file pk.h - * - * \brief 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) - */ - -#ifndef MBEDTLS_PK_WRAP_H -#define MBEDTLS_PK_WRAP_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "pk.h" - -struct mbedtls_pk_info_t -{ - /** Public key type */ - mbedtls_pk_type_t type; - - /** Type name */ - const char *name; - - /** Get key size in bits */ - size_t (*get_bitlen)( const void * ); - - /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ - int (*can_do)( mbedtls_pk_type_t type ); - - /** Verify signature */ - int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); - - /** Make signature */ - int (*sign_func)( 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 ); - - /** Decrypt message */ - int (*decrypt_func)( 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 ); - - /** Encrypt message */ - int (*encrypt_func)( 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 ); - - /** Check public-private key pair */ - int (*check_pair_func)( const void *pub, const void *prv ); - - /** Allocate a new context */ - void * (*ctx_alloc_func)( void ); - - /** Free the given context */ - void (*ctx_free_func)( void *ctx ); - - /** Interface with the debug module */ - void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); - -}; -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* Container for RSA-alt */ -typedef struct -{ - void *key; - mbedtls_pk_rsa_alt_decrypt_func decrypt_func; - mbedtls_pk_rsa_alt_sign_func sign_func; - mbedtls_pk_rsa_alt_key_len_func key_len_func; -} mbedtls_rsa_alt_context; -#endif - -#if defined(MBEDTLS_RSA_C) -extern const mbedtls_pk_info_t mbedtls_rsa_info; -#endif - -#if defined(MBEDTLS_ECP_C) -extern const mbedtls_pk_info_t mbedtls_eckey_info; -extern const mbedtls_pk_info_t mbedtls_eckeydh_info; -#endif - -#if defined(MBEDTLS_ECDSA_C) -extern const mbedtls_pk_info_t mbedtls_ecdsa_info; -#endif - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; -#endif - -#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/components/security/mbedtls/include/mbedtls/pkcs11.h b/components/security/mbedtls/include/mbedtls/pkcs11.h deleted file mode 100644 index 2e889281..00000000 --- a/components/security/mbedtls/include/mbedtls/pkcs11.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * \file pkcs11.h - * - * \brief Wrapper for PKCS#11 library libpkcs11-helper - * - * \author Adriaan de Jong - * - * 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) - */ -#ifndef MBEDTLS_PKCS11_H -#define MBEDTLS_PKCS11_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PKCS11_C) - -#include "x509_crt.h" - -#include - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Context for PKCS #11 private keys. - */ -typedef struct { - pkcs11h_certificate_t pkcs11h_cert; - int len; -} mbedtls_pkcs11_context; - -/** - * Initialize a mbedtls_pkcs11_context. - * (Just making memory references valid.) - */ -void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); - -/** - * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. - * - * \param cert X.509 certificate to fill - * \param pkcs11h_cert PKCS #11 helper certificate - * - * \return 0 on success. - */ -int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); - -/** - * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the - * mbedtls_pkcs11_context will take over control of the certificate, freeing it when - * done. - * - * \param priv_key Private key structure to fill. - * \param pkcs11_cert PKCS #11 helper certificate - * - * \return 0 on success - */ -int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert ); - -/** - * Free the contents of the given private key context. Note that the structure - * itself is not freed. - * - * \param priv_key Private key structure to cleanup - */ -void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ); - -/** - * \brief Do an RSA private key decrypt, then remove the message - * padding - * - * \param ctx PKCS #11 context - * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param olen will contain the plaintext length - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Do a private RSA to sign a message digest - * - * \param ctx PKCS #11 context - * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * SSL/TLS wrappers for PKCS#11 functions - */ -static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, - const unsigned char *input, unsigned char *output, - size_t output_max_len ) -{ - return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, - output_max_len ); -} - -static inline int mbedtls_ssl_pkcs11_sign( void *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, - const unsigned char *hash, unsigned char *sig ) -{ - ((void) f_rng); - ((void) p_rng); - return mbedtls_pkcs11_sign( (mbedtls_pkcs11_context *) ctx, mode, md_alg, - hashlen, hash, sig ); -} - -static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) -{ - return ( (mbedtls_pkcs11_context *) ctx )->len; -} - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PKCS11_C */ - -#endif /* MBEDTLS_PKCS11_H */ diff --git a/components/security/mbedtls/include/mbedtls/pkcs5.h b/components/security/mbedtls/include/mbedtls/pkcs5.h deleted file mode 100644 index ec5cb9e7..00000000 --- a/components/security/mbedtls/include/mbedtls/pkcs5.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * \file pkcs5.h - * - * \brief PKCS#5 functions - * - * \author Mathias Olsson - * - * 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) - */ -#ifndef MBEDTLS_PKCS5_H -#define MBEDTLS_PKCS5_H - -#include "asn1.h" -#include "md.h" - -#include -#include - -#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ -#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ -#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ - -#define MBEDTLS_PKCS5_DECRYPT 0 -#define MBEDTLS_PKCS5_ENCRYPT 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PKCS#5 PBES2 function - * - * \param pbe_params the ASN.1 algorithm parameters - * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT - * \param pwd password to use when generating key - * \param pwdlen length of password - * \param data data to process - * \param datalen length of data - * \param output output buffer - * - * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. - */ -int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t datalen, - unsigned char *output ); - -/** - * \brief PKCS#5 PBKDF2 using HMAC - * - * \param ctx Generic HMAC context - * \param password Password to use when generating key - * \param plen Length of password - * \param salt Salt to use when generating key - * \param slen Length of salt - * \param iteration_count Iteration count - * \param key_length Length of generated key in bytes - * \param output Generated key. Must be at least as big as key_length - * - * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. - */ -int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, - size_t plen, const unsigned char *salt, size_t slen, - unsigned int iteration_count, - uint32_t key_length, unsigned char *output ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_pkcs5_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* pkcs5.h */ diff --git a/components/security/mbedtls/include/mbedtls/platform.h b/components/security/mbedtls/include/mbedtls/platform.h deleted file mode 100644 index 36148c0b..00000000 --- a/components/security/mbedtls/include/mbedtls/platform.h +++ /dev/null @@ -1,305 +0,0 @@ -/** - * \file platform.h - * - * \brief mbed TLS Platform abstraction layer - * - * Copyright (C) 2006-2016, 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) - */ -#ifndef MBEDTLS_PLATFORM_H -#define MBEDTLS_PLATFORM_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if !defined(MBEDTLS_PLATFORM_ALT) - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) -#include -#include -#include -#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) -#if defined(_WIN32) -#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< Default snprintf to use */ -#else -#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use */ -#endif -#endif -#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) -#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) -#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) -#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_FREE) -#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT) -#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_TIME) -#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) -#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< Default exit value to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) -#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< Default exit value to use */ -#endif -#if defined(MBEDTLS_FS_IO) -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) -#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read -#endif -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) -#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write -#endif -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) -#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" -#endif -#endif /* MBEDTLS_FS_IO */ -#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ -#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) -#include MBEDTLS_PLATFORM_STD_MEM_HDR -#endif -#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ - - -/* \} name SECTION: Module settings */ - -/* - * The function pointers for calloc and free - */ -#if defined(MBEDTLS_PLATFORM_MEMORY) -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ - defined(MBEDTLS_PLATFORM_CALLOC_MACRO) -#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO -#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO -#else -/* For size_t */ -#include -extern void * (*mbedtls_calloc)( size_t n, size_t size ); -extern void (*mbedtls_free)( void *ptr ); - -/** - * \brief Set your own memory implementation function pointers - * - * \param calloc_func the calloc function implementation - * \param free_func the free function implementation - * - * \return 0 if successful - */ -int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), - void (*free_func)( void * ) ); -#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ -#else /* !MBEDTLS_PLATFORM_MEMORY */ -#include -#define mbedtls_calloc mycalloc -#define mbedtls_free vPortFree -#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ - -/* - * The function pointers for fprintf - */ -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) -/* We need FILE * */ -#include -extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); - -/** - * \brief Set your own fprintf function pointer - * - * \param fprintf_func the fprintf function implementation - * - * \return 0 - */ -int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, - ... ) ); -#else -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) -#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO -#else -#define mbedtls_fprintf fprintf -#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ - -/* - * The function pointers for printf - */ -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) -extern int (*mbedtls_printf)( const char *format, ... ); - -/** - * \brief Set your own printf function pointer - * - * \param printf_func the printf function implementation - * - * \return 0 - */ -int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); -#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) -#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO -#else -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ - -/* - * The function pointers for snprintf - * - * The snprintf implementation should conform to C99: - * - it *must* always correctly zero-terminate the buffer - * (except when n == 0, then it must leave the buffer untouched) - * - however it is acceptable to return -1 instead of the required length when - * the destination buffer is too short. - */ -#if defined(_WIN32) -/* For Windows (inc. MSYS2), we provide our own fixed implementation */ -int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); - -/** - * \brief Set your own snprintf function pointer - * - * \param snprintf_func the snprintf function implementation - * - * \return 0 - */ -int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, - const char * format, ... ) ); -#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) -#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO -#else -#define mbedtls_snprintf snprintf -#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ - -/* - * The function pointers for exit - */ -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) -extern void (*mbedtls_exit)( int status ); - -/** - * \brief Set your own exit function pointer - * - * \param exit_func the exit function implementation - * - * \return 0 - */ -int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); -#else -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) -#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO -#else -#define mbedtls_exit exit -#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ -#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ - -/* - * The default exit values - */ -#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) -#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS -#else -#define MBEDTLS_EXIT_SUCCESS 0 -#endif -#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) -#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE -#else -#define MBEDTLS_EXIT_FAILURE 1 -#endif - -/* - * The function pointers for reading from and writing a seed file to - * Non-Volatile storage (NV) in a platform-independent way - * - * Only enabled when the NV seed entropy source is enabled - */ -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) -/* Internal standard platform definitions */ -int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); -int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); -extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); - -/** - * \brief Set your own seed file writing/reading functions - * - * \param nv_seed_read_func the seed reading function implementation - * \param nv_seed_write_func the seed writing function implementation - * - * \return 0 - */ -int mbedtls_platform_set_nv_seed( - int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), - int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) - ); -#else -#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ - defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) -#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO -#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO -#else -#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read -#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write -#endif -#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_PLATFORM_ALT */ - -#include "platform_alt.h" - -#endif /* MBEDTLS_PLATFORM_ALT */ - - -#endif /* platform.h */ diff --git a/components/security/mbedtls/include/mbedtls/platform_alt.h b/components/security/mbedtls/include/mbedtls/platform_alt.h deleted file mode 100644 index dafb98d0..00000000 --- a/components/security/mbedtls/include/mbedtls/platform_alt.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (C) 2018 The YunOS IoT Project. All rights reserved. - */ - -#ifndef MBEDTLS_PLATFORM_ALT_H -#define MBEDTLS_PLATFORM_ALT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define mbedtls_time time -#define mbedtls_snprintf snprintf - -typedef time_t mbedtls_time_t; - -void *mbedtls_calloc( size_t n, size_t size ); -void mbedtls_free( void *ptr ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PLATFORM_ALT_H */ diff --git a/components/security/mbedtls/include/mbedtls/platform_time.h b/components/security/mbedtls/include/mbedtls/platform_time.h deleted file mode 100644 index abb34314..00000000 --- a/components/security/mbedtls/include/mbedtls/platform_time.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file platform_time.h - * - * \brief mbed TLS Platform time abstraction - * - * Copyright (C) 2006-2016, 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) - */ -#ifndef MBEDTLS_PLATFORM_TIME_H -#define MBEDTLS_PLATFORM_TIME_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -/* - * The time_t datatype - */ -#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) -typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; -#else -/* For time_t */ -#include -typedef time_t mbedtls_time_t; -#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ - -/* - * The function pointers for time - */ -#if defined(MBEDTLS_PLATFORM_TIME_ALT) -extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); - -/** - * \brief Set your own time function pointer - * - * \param time_func the time function implementation - * - * \return 0 - */ -int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); -#else -#if defined(MBEDTLS_PLATFORM_TIME_MACRO) -#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO -#else -#define mbedtls_time time -#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ -#endif /* MBEDTLS_PLATFORM_TIME_ALT */ - -#ifdef __cplusplus -} -#endif - -#endif /* platform_time.h */ diff --git a/components/security/mbedtls/include/mbedtls/rsa.h b/components/security/mbedtls/include/mbedtls/rsa.h deleted file mode 100644 index 0b184f24..00000000 --- a/components/security/mbedtls/include/mbedtls/rsa.h +++ /dev/null @@ -1,658 +0,0 @@ -/** - * \file rsa.h - * - * \brief The RSA public-key cryptosystem - * - * 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) - */ -#ifndef MBEDTLS_RSA_H -#define MBEDTLS_RSA_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if !defined(MBEDTLS_PK_ALT) - -#include "bignum.h" -#include "md.h" - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -/* - * RSA Error codes - */ -#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ -#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ -#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the library's validity check. */ -#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ -#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ -#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ -#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ -#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ - -/* - * RSA constants - */ -#define MBEDTLS_RSA_PUBLIC 0 -#define MBEDTLS_RSA_PRIVATE 1 - -#define MBEDTLS_RSA_PKCS_V15 0 -#define MBEDTLS_RSA_PKCS_V21 1 - -#define MBEDTLS_RSA_SIGN 1 -#define MBEDTLS_RSA_CRYPT 2 - -#define MBEDTLS_RSA_SALT_LEN_ANY -1 - -/* - * The above constants may be used even if the RSA module is compile out, - * eg for alternative (PKCS#11) RSA implemenations in the PK layers. - */ -#if defined(MBEDTLS_RSA_C) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief RSA context structure - */ -typedef struct -{ - int ver; /*!< always 0 */ - size_t len; /*!< size(N) in chars */ - - mbedtls_mpi N; /*!< public modulus */ - mbedtls_mpi E; /*!< public exponent */ - - mbedtls_mpi D; /*!< private exponent */ - mbedtls_mpi P; /*!< 1st prime factor */ - mbedtls_mpi Q; /*!< 2nd prime factor */ - mbedtls_mpi DP; /*!< D % (P - 1) */ - mbedtls_mpi DQ; /*!< D % (Q - 1) */ - mbedtls_mpi QP; /*!< 1 / (Q % P) */ - - mbedtls_mpi RN; /*!< cached R^2 mod N */ - mbedtls_mpi RP; /*!< cached R^2 mod P */ - mbedtls_mpi RQ; /*!< cached R^2 mod Q */ - - mbedtls_mpi Vi; /*!< cached blinding value */ - mbedtls_mpi Vf; /*!< cached un-blinding value */ - - int padding; /*!< MBEDTLS_RSA_PKCS_V15 for 1.5 padding and - MBEDTLS_RSA_PKCS_v21 for OAEP/PSS */ - int hash_id; /*!< Hash identifier of mbedtls_md_type_t as - specified in the mbedtls_md.h header file - for the EME-OAEP and EMSA-PSS - encoding */ -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex */ -#endif -} -mbedtls_rsa_context; - -/** - * \brief Initialize an RSA context - * - * Note: Set padding to MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP - * encryption scheme and the RSASSA-PSS signature scheme. - * - * \param ctx RSA context to be initialized - * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 - * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier - * - * \note The hash_id parameter is actually ignored - * when using MBEDTLS_RSA_PKCS_V15 padding. - * - * \note Choice of padding mode is strictly enforced for private key - * operations, since there might be security concerns in - * mixing padding modes. For public key operations it's merely - * a default value, which can be overriden by calling specific - * rsa_rsaes_xxx or rsa_rsassa_xxx functions. - * - * \note The chosen hash is always used for OEAP encryption. - * For PSS signatures, it's always used for making signatures, - * but can be overriden (and always is, if set to - * MBEDTLS_MD_NONE) for verifying them. - */ -void mbedtls_rsa_init( mbedtls_rsa_context *ctx, - int padding, - int hash_id); - -/** - * \brief Set padding for an already initialized RSA context - * See \c mbedtls_rsa_init() for details. - * - * \param ctx RSA context to be set - * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 - * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier - */ -void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id); - -/** - * \brief Generate an RSA keypair - * - * \param ctx RSA context that will hold the key - * \param f_rng RNG function - * \param p_rng RNG parameter - * \param nbits size of the public key in bits - * \param exponent public exponent (e.g., 65537) - * - * \note mbedtls_rsa_init() must be called beforehand to setup - * the RSA context. - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - */ -int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ); - -/** - * \brief Check a public RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - */ -int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); - -/** - * \brief Check a private RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - */ -int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); - -/** - * \brief Check a public-private RSA key pair. - * Check each of the contexts, and make sure they match. - * - * \param pub RSA context holding the public key - * \param prv RSA context holding the private key - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - */ -int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ); - -/** - * \brief Do an RSA public key operation - * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note This function does NOT take care of message - * padding. Also, be sure to set input[0] = 0 or ensure that - * input is smaller than N. - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_public( mbedtls_rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Do an RSA private key operation - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for blinding) - * \param p_rng RNG parameter - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_private( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Generic wrapper to perform a PKCS#1 encryption using the - * mode from the context. Add the message padding, then do an - * RSA operation. - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding - * and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding - * and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param label buffer holding the custom label to use - * \param label_len contains the label length - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Generic wrapper to perform a PKCS#1 decryption using the - * mode from the context. Do an RSA operation, then remove - * the message padding - * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param label buffer holding the custom label to use - * \param label_len contains the label length - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Generic wrapper to perform a PKCS#1 signature using the - * mode from the context. Do a private RSA operation to sign - * a message digest - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for - * MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding, see comments on - * \note \c mbedtls_rsa_rsassa_pss_sign() for details on md_alg and hash_id. - */ -int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) - * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for - * MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note The hash_id in the RSA context is the one used for the - * encoding. md_alg in the function call is the type of hash - * that is encoded. According to RFC 3447 it is advised to - * keep both hashes the same. - */ -int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Generic wrapper to perform a PKCS#1 verification using the - * mode from the context. Do a public RSA operation and check - * the message digest - * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding, see comments on - * \c mbedtls_rsa_rsassa_pss_verify() about md_alg and hash_id. - */ -int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) - * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) - * (This is the "simple" version.) - * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note The hash_id in the RSA context is the one used for the - * verification. md_alg in the function call is the type of - * hash that is verified. According to RFC 3447 it is advised to - * keep both hashes the same. If hash_id in the RSA context is - * unset, the md_alg from the function call is used. - */ -int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) - * (This is the version with "full" options.) - * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param mgf1_hash_id message digest used for mask generation - * \param expected_salt_len Length of the salt used in padding, use - * MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note The hash_id in the RSA context is ignored. - */ -int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - mbedtls_md_type_t mgf1_hash_id, - int expected_salt_len, - const unsigned char *sig ); - -/** - * \brief Copy the components of an RSA context - * - * \param dst Destination context - * \param src Source context - * - * \return 0 on success, - * MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure - */ -int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); - -/** - * \brief Free the components of an RSA key - * - * \param ctx RSA Context to free - */ -void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_rsa_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_RSA_C */ - -#else /* MBEDTLS_PK_ALT */ -#include "rsa_alt.h" -#endif /* MBEDTLS_PK_ALT */ - -#endif /* rsa.h */ diff --git a/components/security/mbedtls/include/mbedtls/rsa_alt.h b/components/security/mbedtls/include/mbedtls/rsa_alt.h deleted file mode 100644 index e0c3d78d..00000000 --- a/components/security/mbedtls/include/mbedtls/rsa_alt.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef MBEDTLS_RSA_ALT_H -#define MBEDTLS_RSA_ALT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define MBEDTLS_RSA_ALT_PKCS_V15 0 -#define MBEDTLS_RSA_ALT_PKCS_V21 1 - -/** - * \brief RSA context structure - */ -typedef struct -{ - size_t n_len; - size_t e_len; - - unsigned char *rsa_n; - unsigned char *rsa_e; - - int padding; - int hash_id; -} mbedtls_rsa_context; - -int rsa_verify_alt(void *ctx, size_t hash_id, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); -int rsa_sign_alt(void *ctx, size_t hash_id, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len); - -int rsa_decrypt_alt(void *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen); -int rsa_encrypt_alt(void *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen); - -void mbedtls_rsa_init_alt(mbedtls_rsa_context *ctx, - int padding, int hash_id); -void mbedtls_rsa_free_alt(mbedtls_rsa_context *ctx); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_RSA_ALT_H */ diff --git a/components/security/mbedtls/include/mbedtls/sha1.h b/components/security/mbedtls/include/mbedtls/sha1.h deleted file mode 100644 index a7fec9d9..00000000 --- a/components/security/mbedtls/include/mbedtls/sha1.h +++ /dev/null @@ -1,137 +0,0 @@ -/** - * \file sha1.h - * - * \brief SHA-1 cryptographic hash function - * - * 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) - */ -#ifndef MBEDTLS_SHA1_H -#define MBEDTLS_SHA1_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_SHA1_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-1 context structure - */ -typedef struct { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -mbedtls_sha1_context; - -/** - * \brief Initialize SHA-1 context - * - * \param ctx SHA-1 context to be initialized - */ -void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); - -/** - * \brief Clear SHA-1 context - * - * \param ctx SHA-1 context to be cleared - */ -void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-1 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha1_clone( mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src ); - -/** - * \brief SHA-1 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); - -/** - * \brief SHA-1 process buffer - * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-1 final digest - * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); - -/* Internal use */ -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA1_ALT */ -#include "sha1_alt.h" -#endif /* MBEDTLS_SHA1_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_SHA1_ALT) -/** - * \brief Output = SHA-1( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-1 checksum result - */ -void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); -#endif /* MBEDTLS_SHA1_ALT */ - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_sha1_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_sha1.h */ diff --git a/components/security/mbedtls/include/mbedtls/sha1_alt.h b/components/security/mbedtls/include/mbedtls/sha1_alt.h deleted file mode 100644 index 45e73e48..00000000 --- a/components/security/mbedtls/include/mbedtls/sha1_alt.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2018 The YunOS IoT Project. All rights reserved. - */ - -#ifndef MBEDTLS_SHA1_ALT_H -#define MBEDTLS_SHA1_ALT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - size_t size; - void *ali_ctx; -} mbedtls_sha1_context; - -void mbedtls_sha1_init_alt(mbedtls_sha1_context *ctx); -void mbedtls_sha1_free_alt(mbedtls_sha1_context *ctx); - -void mbedtls_sha1_clone_alt(mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src); - -void mbedtls_sha1_starts_alt(mbedtls_sha1_context *ctx); -void mbedtls_sha1_update_alt(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen); -void mbedtls_sha1_finish_alt(mbedtls_sha1_context *ctx, unsigned char output[20]); - -void mbedtls_sha1_alt( const unsigned char *input, size_t ilen, unsigned char output[20] ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_SHA1_ALT_H */ diff --git a/components/security/mbedtls/include/mbedtls/sha256.h b/components/security/mbedtls/include/mbedtls/sha256.h deleted file mode 100644 index 709c06fd..00000000 --- a/components/security/mbedtls/include/mbedtls/sha256.h +++ /dev/null @@ -1,157 +0,0 @@ -/** - * \file sha256.h - * - * \brief SHA-224 and SHA-256 cryptographic hash function - * - * 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) - */ -#ifndef MBEDTLS_SHA256_H -#define MBEDTLS_SHA256_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_SHA256_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-256 context structure - */ -typedef struct { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[8]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - int is224; /*!< 0 => SHA-256, else SHA-224 */ - size_t size; - void *ali_ctx; -} -mbedtls_sha256_context; - -/** - * \brief Initialize SHA-256 context - * - * \param ctx SHA-256 context to be initialized - */ -void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); - -/** - * \brief Clear SHA-256 context - * - * \param ctx SHA-256 context to be cleared - */ -void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-256 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha256_clone( mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src ); - -/** - * \brief SHA-256 context setup - * - * \param ctx context to be initialized - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); - -/** - * \brief SHA-256 process buffer - * - * \param ctx SHA-256 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-256 final digest - * - * \param ctx SHA-256 context - * \param output SHA-224/256 checksum result - */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); - -/* Internal use */ -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); - - -void mbedtls_sha256_init_alt(mbedtls_sha256_context *ctx); -void mbedtls_sha256_free_alt(mbedtls_sha256_context *ctx); - -void mbedtls_sha256_clone_alt(mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src); - -void mbedtls_sha256_starts_alt(mbedtls_sha256_context *ctx, int is224); -void mbedtls_sha256_update_alt(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen); -void mbedtls_sha256_finish_alt(mbedtls_sha256_context *ctx, unsigned char output[32]); - -void mbedtls_sha256_alt(const unsigned char *input, size_t ilen, unsigned char output[32], int is224); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA256_ALT */ -#include "sha256_alt.h" -#endif /* MBEDTLS_SHA256_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_SHA256_ALT) -/** - * \brief Output = SHA-256( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-224/256 checksum result - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void mbedtls_sha256( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ); -#endif /* MBEDTLS_SHA256_ALT */ - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_sha256_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_sha256.h */ diff --git a/components/security/mbedtls/include/mbedtls/sha256_alt.h b/components/security/mbedtls/include/mbedtls/sha256_alt.h deleted file mode 100644 index 4be792c7..00000000 --- a/components/security/mbedtls/include/mbedtls/sha256_alt.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2018 The YunOS IoT Project. All rights reserved. - */ - -#ifndef MBEDTLS_SHA256_ALT_H -#define MBEDTLS_SHA256_ALT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - size_t size; - void *ali_ctx; -} mbedtls_sha256_context; - -void mbedtls_sha256_init_alt(mbedtls_sha256_context *ctx); -void mbedtls_sha256_free_alt(mbedtls_sha256_context *ctx); - -void mbedtls_sha256_clone_alt(mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src); - -void mbedtls_sha256_starts_alt(mbedtls_sha256_context *ctx, int is224); -void mbedtls_sha256_update_alt(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen); -void mbedtls_sha256_finish_alt(mbedtls_sha256_context *ctx, unsigned char output[32]); - -void mbedtls_sha256_alt(const unsigned char *input, size_t ilen, unsigned char output[32], int is224); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_SHA256_ALT_H */ diff --git a/components/security/mbedtls/include/mbedtls/sha512.h b/components/security/mbedtls/include/mbedtls/sha512.h deleted file mode 100644 index 627694f4..00000000 --- a/components/security/mbedtls/include/mbedtls/sha512.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * \file sha512.h - * - * \brief SHA-384 and SHA-512 cryptographic hash function - * - * 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) - */ -#ifndef MBEDTLS_SHA512_H -#define MBEDTLS_SHA512_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_SHA512_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-512 context structure - */ -typedef struct -{ - uint64_t total[2]; /*!< number of bytes processed */ - uint64_t state[8]; /*!< intermediate digest state */ - unsigned char buffer[128]; /*!< data block being processed */ - int is384; /*!< 0 => SHA-512, else SHA-384 */ -} -mbedtls_sha512_context; - -/** - * \brief Initialize SHA-512 context - * - * \param ctx SHA-512 context to be initialized - */ -void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); - -/** - * \brief Clear SHA-512 context - * - * \param ctx SHA-512 context to be cleared - */ -void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-512 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha512_clone( mbedtls_sha512_context *dst, - const mbedtls_sha512_context *src ); - -/** - * \brief SHA-512 context setup - * - * \param ctx context to be initialized - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); - -/** - * \brief SHA-512 process buffer - * - * \param ctx SHA-512 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-512 final digest - * - * \param ctx SHA-512 context - * \param output SHA-384/512 checksum result - */ -void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA512_ALT */ -#include "sha512_alt.h" -#endif /* MBEDTLS_SHA512_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = SHA-512( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-384/512 checksum result - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void mbedtls_sha512( const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_sha512_self_test( int verbose ); - -/* Internal use */ -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_sha512.h */ diff --git a/components/security/mbedtls/include/mbedtls/ssl.h b/components/security/mbedtls/include/mbedtls/ssl.h deleted file mode 100644 index d0456701..00000000 --- a/components/security/mbedtls/include/mbedtls/ssl.h +++ /dev/null @@ -1,2559 +0,0 @@ -/** - * \file ssl.h - * - * \brief SSL/TLS 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) - */ -#ifndef MBEDTLS_SSL_H -#define MBEDTLS_SSL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "bignum.h" -#include "ecp.h" - -#include "ssl_ciphersuites.h" - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#include "x509_crt.h" -#include "x509_crl.h" -#endif - -#if defined(MBEDTLS_DHM_C) -#include "dhm.h" -#endif - -#if defined(MBEDTLS_ECDH_C) -#include "ecdh.h" -#endif - -#if defined(MBEDTLS_ZLIB_SUPPORT) -#include "zlib.h" -#endif - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -/* - * SSL Error codes - */ -#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ -#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ -#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ -#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ -#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ -#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ -#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ -#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ -#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ -#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ -#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ -#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ -#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ -#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ -#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ -#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ -#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ -#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ -#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ -#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ -#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ -#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ -#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ -#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ -#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ -#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ -#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ -#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ -#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ -#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ -#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ -#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ -#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ -#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ -#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ -#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ -#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ -#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ - -/* - * Various constants - */ -#define MBEDTLS_SSL_MAJOR_VERSION_3 3 -#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ -#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ -#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ -#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ - -#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ -#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ - -#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ - -/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c - * NONE must be zero so that memset()ing structure to zero works */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ - -#define MBEDTLS_SSL_IS_CLIENT 0 -#define MBEDTLS_SSL_IS_SERVER 1 - -#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 -#define MBEDTLS_SSL_IS_FALLBACK 1 - -#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 -#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 - -#define MBEDTLS_SSL_ETM_DISABLED 0 -#define MBEDTLS_SSL_ETM_ENABLED 1 - -#define MBEDTLS_SSL_COMPRESS_NULL 0 -#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 - -#define MBEDTLS_SSL_VERIFY_NONE 0 -#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 -#define MBEDTLS_SSL_VERIFY_REQUIRED 2 -#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ - -#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 -#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 - -#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 -#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 - -#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 -#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 - -#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 -#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 - -#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 -#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 -#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 - -#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 -#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 -#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ - -#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 -#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 - -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 - -#define MBEDTLS_SSL_ARC4_ENABLED 0 -#define MBEDTLS_SSL_ARC4_DISABLED 1 - -#define MBEDTLS_SSL_PRESET_DEFAULT 0 -#define MBEDTLS_SSL_PRESET_SUITEB 2 - -/* - * Default range for DTLS retransmission timer value, in milliseconds. - * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. - */ -#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 -#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) -#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ -#endif - -/* - * Maxium fragment length in bytes, - * determines the size of each of the two internal I/O buffers. - * - * Note: the RFC defines the default size of SSL / TLS messages. If you - * change the value here, other clients / servers may not be able to - * communicate with you anymore. Only change this value if you control - * both sides of the connection and have it reduced at both sides, or - * if you're using the Max Fragment Length extension and you know all your - * peers are using it too! - */ -#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) -#define MBEDTLS_SSL_MAX_CONTENT_LEN (4*1024) /**< ali default value. Size of the input / output buffer */ -#endif - -/* \} name SECTION: Module settings */ - -/* - * Length of the verify data for secure renegotiation - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 -#else -#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 -#endif - -/* - * Signaling ciphersuite values (SCSV) - */ -#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ -#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ - -/* - * Supported Signature and Hash algorithms (For TLS 1.2) - * RFC 5246 section 7.4.1.4.1 - */ -#define MBEDTLS_SSL_HASH_NONE 0 -#define MBEDTLS_SSL_HASH_MD5 1 -#define MBEDTLS_SSL_HASH_SHA1 2 -#define MBEDTLS_SSL_HASH_SHA224 3 -#define MBEDTLS_SSL_HASH_SHA256 4 -#define MBEDTLS_SSL_HASH_SHA384 5 -#define MBEDTLS_SSL_HASH_SHA512 6 - -#define MBEDTLS_SSL_SIG_ANON 0 -#define MBEDTLS_SSL_SIG_RSA 1 -#define MBEDTLS_SSL_SIG_ECDSA 3 - -/* - * Client Certificate Types - * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 - */ -#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 -#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 - -/* - * Message, alert and handshake types - */ -#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 -#define MBEDTLS_SSL_MSG_ALERT 21 -#define MBEDTLS_SSL_MSG_HANDSHAKE 22 -#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 - -#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 -#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 - -#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ -#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ -#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ -#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ -#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ -#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ -#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ -#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ -#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ -#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ -#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ -#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ -#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ -#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ -#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ -#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ -#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ -#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ -#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ -#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ -#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ -#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ -#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ -#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ -#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ -#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ -#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ -#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ -#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ - -#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 -#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 -#define MBEDTLS_SSL_HS_SERVER_HELLO 2 -#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 -#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 -#define MBEDTLS_SSL_HS_CERTIFICATE 11 -#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 -#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 -#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 -#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 -#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 -#define MBEDTLS_SSL_HS_FINISHED 20 - -/* - * TLS extensions - */ -#define MBEDTLS_TLS_EXT_SERVERNAME 0 -#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 - -#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 - -#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 - -#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 -#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 - -#define MBEDTLS_TLS_EXT_SIG_ALG 13 - -#define MBEDTLS_TLS_EXT_ALPN 16 - -#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ -#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ - -#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 - -#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ - -#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 - -/* - * Size defines - */ -#if !defined(MBEDTLS_PSK_MAX_LEN) -#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ -#endif - -/* Dummy type used only for its size */ -union mbedtls_ssl_premaster_secret -{ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE - + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES - + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ -#endif -}; - -#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * SSL state machine - */ -typedef enum -{ - MBEDTLS_SSL_HELLO_REQUEST, - MBEDTLS_SSL_CLIENT_HELLO, - MBEDTLS_SSL_SERVER_HELLO, - MBEDTLS_SSL_SERVER_CERTIFICATE, - MBEDTLS_SSL_SERVER_KEY_EXCHANGE, - MBEDTLS_SSL_CERTIFICATE_REQUEST, - MBEDTLS_SSL_SERVER_HELLO_DONE, - MBEDTLS_SSL_CLIENT_CERTIFICATE, - MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, - MBEDTLS_SSL_CERTIFICATE_VERIFY, - MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, - MBEDTLS_SSL_CLIENT_FINISHED, - MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, - MBEDTLS_SSL_SERVER_FINISHED, - MBEDTLS_SSL_FLUSH_BUFFERS, - MBEDTLS_SSL_HANDSHAKE_WRAPUP, - MBEDTLS_SSL_HANDSHAKE_OVER, - MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, - MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, -} -mbedtls_ssl_states; - -/** - * \brief Callback type: send data on the network. - * - * \note That callback may be either blocking or non-blocking. - * - * \param ctx Context for the send callback (typically a file descriptor) - * \param buf Buffer holding the data to send - * \param len Length of the data to send - * - * \return The callback must return the number of bytes sent if any, - * or a non-zero error code. - * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE - * must be returned when the operation would block. - * - * \note The callback is allowed to send fewer bytes than requested. - * It must always return the number of bytes actually sent. - */ -typedef int mbedtls_ssl_send_t( void *ctx, - const unsigned char *buf, - size_t len ); - -/** - * \brief Callback type: receive data from the network. - * - * \note That callback may be either blocking or non-blocking. - * - * \param ctx Context for the receive callback (typically a file - * descriptor) - * \param buf Buffer to write the received data to - * \param len Length of the receive buffer - * - * \return The callback must return the number of bytes received, - * or a non-zero error code. - * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ - * must be returned when the operation would block. - * - * \note The callback may receive fewer bytes than the length of the - * buffer. It must always return the number of bytes actually - * received and written to the buffer. - */ -typedef int mbedtls_ssl_recv_t( void *ctx, - unsigned char *buf, - size_t len ); - -/** - * \brief Callback type: receive data from the network, with timeout - * - * \note That callback must block until data is received, or the - * timeout delay expires, or the operation is interrupted by a - * signal. - * - * \param ctx Context for the receive callback (typically a file descriptor) - * \param buf Buffer to write the received data to - * \param len Length of the receive buffer - * \param timeout Maximum nomber of millisecondes to wait for data - * 0 means no timeout (potentially waiting forever) - * - * \return The callback must return the number of bytes received, - * or a non-zero error code: - * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, - * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. - * - * \note The callback may receive fewer bytes than the length of the - * buffer. It must always return the number of bytes actually - * received and written to the buffer. - */ -typedef int mbedtls_ssl_recv_timeout_t( void *ctx, - unsigned char *buf, - size_t len, - uint32_t timeout ); -/** - * \brief Callback type: set a pair of timers/delays to watch - * - * \param ctx Context pointer - * \param int_ms Intermediate delay in milliseconds - * \param fin_ms Final delay in milliseconds - * 0 cancels the current timer. - * - * \note This callback must at least store the necessary information - * for the associated \c mbedtls_ssl_get_timer_t callback to - * return correct information. - * - * \note If using a event-driven style of programming, an event must - * be generated when the final delay is passed. The event must - * cause a call to \c mbedtls_ssl_handshake() with the proper - * SSL context to be scheduled. Care must be taken to ensure - * that at most one such call happens at a time. - * - * \note Only one timer at a time must be running. Calling this - * function while a timer is running must cancel it. Cancelled - * timers must not generate any event. - */ -typedef void mbedtls_ssl_set_timer_t( void * ctx, - uint32_t int_ms, - uint32_t fin_ms ); - -/** - * \brief Callback type: get status of timers/delays - * - * \param ctx Context pointer - * - * \return This callback must return: - * -1 if cancelled (fin_ms == 0), - * 0 if none of the delays have passed, - * 1 if only the intermediate delay has passed, - * 2 if the final delay has passed. - */ -typedef int mbedtls_ssl_get_timer_t( void * ctx ); - - -/* Defined below */ -typedef struct mbedtls_ssl_session mbedtls_ssl_session; -typedef struct mbedtls_ssl_context mbedtls_ssl_context; -typedef struct mbedtls_ssl_config mbedtls_ssl_config; - -/* Defined in ssl_internal.h */ -typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; -typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; -#if defined(MBEDTLS_X509_CRT_PARSE_C) -typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; -#endif -#if defined(MBEDTLS_SSL_PROTO_DTLS) -typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; -#endif - -/* - * This structure is used for storing current session data. - */ -struct mbedtls_ssl_session -{ -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t start; /*!< starting time */ -#endif - int ciphersuite; /*!< chosen ciphersuite */ - int compression; /*!< chosen compression */ - size_t id_len; /*!< session id length */ - unsigned char id[32]; /*!< session identifier */ - unsigned char master[48]; /*!< the master secret */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - uint32_t verify_result; /*!< verification result */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - unsigned char *ticket; /*!< RFC 5077 session ticket */ - size_t ticket_len; /*!< session ticket length */ - uint32_t ticket_lifetime; /*!< ticket lifetime hint */ -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - int trunc_hmac; /*!< flag for truncated hmac activation */ -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - int encrypt_then_mac; /*!< flag for EtM activation */ -#endif -}; - -/** - * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. - */ -struct mbedtls_ssl_config -{ - /* Group items by size (largest first) to minimize padding overhead */ - - /* - * Pointers - */ - - const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ - - /** Callback for printing debug output */ - void (*f_dbg)(void *, int, const char *, int, const char *); - void *p_dbg; /*!< context for the debug function */ - - /** Callback for getting (pseudo-)random numbers */ - int (*f_rng)(void *, unsigned char *, size_t); - void *p_rng; /*!< context for the RNG function */ - - /** Callback to retrieve a session from the cache */ - int (*f_get_cache)(void *, mbedtls_ssl_session *); - /** Callback to store a session into the cache */ - int (*f_set_cache)(void *, const mbedtls_ssl_session *); - void *p_cache; /*!< context for cache callbacks */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - /** Callback for setting cert according to SNI extension */ - int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); - void *p_sni; /*!< context for SNI callback */ -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - /** Callback to customize X.509 certificate chain verification */ - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); - void *p_vrfy; /*!< context for X.509 verify calllback */ -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - /** Callback to retrieve PSK key from identity */ - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); - void *p_psk; /*!< context for PSK callback */ -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - /** Callback to create & write a cookie for ClientHello veirifcation */ - int (*f_cookie_write)( void *, unsigned char **, unsigned char *, - const unsigned char *, size_t ); - /** Callback to verify validity of a ClientHello cookie */ - int (*f_cookie_check)( void *, const unsigned char *, size_t, - const unsigned char *, size_t ); - void *p_cookie; /*!< context for the cookie callbacks */ -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) - /** Callback to create & write a session ticket */ - int (*f_ticket_write)( void *, const mbedtls_ssl_session *, - unsigned char *, const unsigned char *, size_t *, uint32_t * ); - /** Callback to parse a session ticket into a session structure */ - int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); - void *p_ticket; /*!< context for the ticket callbacks */ -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - /** Callback to export key block and master secret */ - int (*f_export_keys)( void *, const unsigned char *, - const unsigned char *, size_t, size_t, size_t ); - void *p_export_keys; /*!< context for key export callback */ -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ - mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ - mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ - mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - const int *sig_hashes; /*!< allowed signature hashes */ -#endif - -#if defined(MBEDTLS_ECP_C) - const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ -#endif - -#if defined(MBEDTLS_DHM_C) - mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ - mbedtls_mpi dhm_G; /*!< generator for DHM */ -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char *psk; /*!< pre-shared key */ - size_t psk_len; /*!< length of the pre-shared key */ - unsigned char *psk_identity; /*!< identity for PSK negotiation */ - size_t psk_identity_len;/*!< length of identity */ -#endif - -#if defined(MBEDTLS_SSL_ALPN) - const char **alpn_list; /*!< ordered list of protocols */ -#endif - - /* - * Numerical settings (int then char) - */ - - uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - uint32_t hs_timeout_min; /*!< initial value of the handshake - retransmission timeout (ms) */ - uint32_t hs_timeout_max; /*!< maximum value of the handshake - retransmission timeout (ms) */ -#endif - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renego_max_records; /*!< grace period for renegotiation */ - unsigned char renego_period[8]; /*!< value of the record counters - that triggers renegotiation */ -#endif - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - unsigned int badmac_limit; /*!< limit of records with a bad MAC */ -#endif - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) - unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ -#endif - - unsigned char max_major_ver; /*!< max. major version used */ - unsigned char max_minor_ver; /*!< max. minor version used */ - unsigned char min_major_ver; /*!< min. major version used */ - unsigned char min_minor_ver; /*!< min. minor version used */ - - /* - * Flags (bitfields) - */ - - unsigned int endpoint : 1; /*!< 0: client, 1: server */ - unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ - unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ - /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ - unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ -#if defined(MBEDTLS_ARC4_C) - unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites? */ -#endif -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - unsigned int mfl_code : 3; /*!< desired fragment length */ -#endif -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac? */ -#endif -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ -#endif -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - unsigned int anti_replay : 1; /*!< detect and prevent replay? */ -#endif -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - unsigned int cbc_record_splitting : 1; /*!< do cbc record splitting */ -#endif -#if defined(MBEDTLS_SSL_RENEGOTIATION) - unsigned int disable_renegotiation : 1; /*!< disable renegotiation? */ -#endif -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - unsigned int trunc_hmac : 1; /*!< negotiate truncated hmac? */ -#endif -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - unsigned int session_tickets : 1; /*!< use session tickets? */ -#endif -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) - unsigned int fallback : 1; /*!< is this a fallback? */ -#endif -}; - - -struct mbedtls_ssl_context -{ - const mbedtls_ssl_config *conf; /*!< configuration information */ - - /* - * Miscellaneous - */ - int state; /*!< SSL handshake: current state */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renego_status; /*!< Initial, in progress, pending? */ - int renego_records_seen; /*!< Records since renego request, or with DTLS, - number of retransmissions of request if - renego_max_records is < 0 */ -#endif - - int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ - int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - unsigned badmac_seen; /*!< records with a bad MAC received */ -#endif - - mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ - mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ - mbedtls_ssl_recv_timeout_t *f_recv_timeout; - /*!< Callback for network receive with timeout */ - - void *p_bio; /*!< context for I/O operations */ - - /* - * Session layer - */ - mbedtls_ssl_session *session_in; /*!< current session data (in) */ - mbedtls_ssl_session *session_out; /*!< current session data (out) */ - mbedtls_ssl_session *session; /*!< negotiated session data */ - mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ - - mbedtls_ssl_handshake_params *handshake; /*!< params required only during - the handshake process */ - - /* - * Record layer transformations - */ - mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ - mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ - mbedtls_ssl_transform *transform; /*!< negotiated transform params */ - mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ - - /* - * Timers - */ - void *p_timer; /*!< context for the timer callbacks */ - - mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ - mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ - - /* - * Record layer (incoming data) - */ - unsigned char *in_buf; /*!< input buffer */ - unsigned char *in_ctr; /*!< 64-bit incoming message counter - TLS: maintained by us - DTLS: read from peer */ - unsigned char *in_hdr; /*!< start of record header */ - unsigned char *in_len; /*!< two-bytes message length field */ - unsigned char *in_iv; /*!< ivlen-byte IV */ - unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ - unsigned char *in_offt; /*!< read offset in application data */ - - int in_msgtype; /*!< record header: message type */ - size_t in_msglen; /*!< record header: message length */ - size_t in_left; /*!< amount of data read so far */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - uint16_t in_epoch; /*!< DTLS epoch for incoming records */ - size_t next_record_offset; /*!< offset of the next record in datagram - (equal to in_left if none) */ -#endif -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - uint64_t in_window_top; /*!< last validated record seq_num */ - uint64_t in_window; /*!< bitmask for replay detection */ -#endif - - size_t in_hslen; /*!< current handshake message length, - including the handshake header */ - int nb_zero; /*!< # of 0-length encrypted messages */ - int record_read; /*!< record is already present */ - - /* - * Record layer (outgoing data) - */ - unsigned char *out_buf; /*!< output buffer */ - unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ - unsigned char *out_hdr; /*!< start of record header */ - unsigned char *out_len; /*!< two-bytes message length field */ - unsigned char *out_iv; /*!< ivlen-byte IV */ - unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ - - int out_msgtype; /*!< record header: message type */ - size_t out_msglen; /*!< record header: message length */ - size_t out_left; /*!< amount of data not yet written */ - -#if defined(MBEDTLS_ZLIB_SUPPORT) - unsigned char *compress_buf; /*!< zlib data buffer */ -#endif -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - signed char split_done; /*!< current record already splitted? */ -#endif - - /* - * PKI layer - */ - int client_auth; /*!< flag for client auth. */ - - /* - * User settings - */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - char *hostname; /*!< expected peer CN for verification - (and SNI if available) */ -#endif - -#if defined(MBEDTLS_SSL_ALPN) - const char *alpn_chosen; /*!< negotiated protocol */ -#endif - - /* - * Information for DTLS hello verify - */ -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - unsigned char *cli_id; /*!< transport-level ID of the client */ - size_t cli_id_len; /*!< length of cli_id */ -#endif - - /* - * Secure renegotiation - */ - /* needed to know when to send extension on server */ - int secure_renegotiation; /*!< does peer support legacy or - secure renegotiation */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - size_t verify_data_len; /*!< length of verify data stored */ - char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ - char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ -#endif -}; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - -#define MBEDTLS_SSL_CHANNEL_OUTBOUND 0 -#define MBEDTLS_SSL_CHANNEL_INBOUND 1 - -extern int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen); -extern int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction); -extern int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - -/** - * \brief Returns the list of ciphersuites supported by the SSL/TLS module. - * - * \return a statically allocated array of ciphersuites, the last - * entry is 0. - */ -const int *mbedtls_ssl_list_ciphersuites( void ); - -/** - * \brief Return the name of the ciphersuite associated with the - * given ID - * - * \param ciphersuite_id SSL ciphersuite ID - * - * \return a string containing the ciphersuite name - */ -const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); - -/** - * \brief Return the ID of the ciphersuite associated with the - * given name - * - * \param ciphersuite_name SSL ciphersuite name - * - * \return the ID with the ciphersuite or 0 if not found - */ -int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); - -/** - * \brief Initialize an SSL context - * Just makes the context ready for mbedtls_ssl_setup() or - * mbedtls_ssl_free() - * - * \param ssl SSL context - */ -void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); - -/** - * \brief Set up an SSL context for use - * - * \note No copy of the configuration context is made, it can be - * shared by many mbedtls_ssl_context structures. - * - * \warning Modifying the conf structure after it has been used in this - * function is unsupported! - * - * \param ssl SSL context - * \param conf SSL configuration to use - * - * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if - * memory allocation failed - */ -int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, - const mbedtls_ssl_config *conf ); - -/** - * \brief Reset an already initialized SSL context for re-use - * while retaining application-set variables, function - * pointers and data. - * - * \param ssl SSL context - * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, - MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or - * MBEDTLS_ERR_SSL_COMPRESSION_FAILED - */ -int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); - -/** - * \brief Set the current endpoint type - * - * \param conf SSL configuration - * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER - */ -void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); - -/** - * \brief Set the transport type (TLS or DTLS). - * Default: TLS - * - * \note For DTLS, you must either provide a recv callback that - * doesn't block, or one that handles timeouts, see - * \c mbedtls_ssl_set_bio(). You also need to provide timer - * callbacks with \c mbedtls_ssl_set_timer_cb(). - * - * \param conf SSL configuration - * \param transport transport type: - * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, - * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. - */ -void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); - -/** - * \brief Set the certificate verification mode - * Default: NONE on server, REQUIRED on client - * - * \param conf SSL configuration - * \param authmode can be: - * - * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked - * (default on server) - * (insecure on client) - * - * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the - * handshake continues even if verification failed; - * mbedtls_ssl_get_verify_result() can be called after the - * handshake is complete. - * - * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, - * handshake is aborted if verification failed. - * (default on client) - * - * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. - * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at - * the right time(s), which may not be obvious, while REQUIRED always perform - * the verification as soon as possible. For example, REQUIRED was protecting - * against the "triple handshake" attack even before it was found. - */ -void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Set the verification callback (Optional). - * - * If set, the verify callback is called for each - * certificate in the chain. For implementation - * information, please see \c x509parse_verify() - * - * \param conf SSL configuration - * \param f_vrfy verification function - * \param p_vrfy verification parameter - */ -void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/** - * \brief Set the random number generator callback - * - * \param conf SSL configuration - * \param f_rng RNG function - * \param p_rng RNG parameter - */ -void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Set the debug callback - * - * The callback has the following argument: - * void * opaque context for the callback - * int debug level - * const char * file name - * int line number - * const char * message - * - * \param conf SSL configuration - * \param f_dbg debug function - * \param p_dbg debug parameter - */ -void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, - void (*f_dbg)(void *, int, const char *, int, const char *), - void *p_dbg ); - -/** - * \brief Set the underlying BIO callbacks for write, read and - * read-with-timeout. - * - * \param ssl SSL context - * \param p_bio parameter (context) shared by BIO callbacks - * \param f_send write callback - * \param f_recv read callback - * \param f_recv_timeout blocking read callback with timeout. - * - * \note One of f_recv or f_recv_timeout can be NULL, in which case - * the other is used. If both are non-NULL, f_recv_timeout is - * used and f_recv is ignored (as if it were NULL). - * - * \note The two most common use cases are: - * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL - * - blocking I/O, f_recv == NULL, f_recv_timout != NULL - * - * \note For DTLS, you need to provide either a non-NULL - * f_recv_timeout callback, or a f_recv that doesn't block. - * - * \note See the documentations of \c mbedtls_ssl_sent_t, - * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for - * the conventions those callbacks must follow. - * - * \note On some platforms, net_sockets.c provides - * \c mbedtls_net_send(), \c mbedtls_net_recv() and - * \c mbedtls_net_recv_timeout() that are suitable to be used - * here. - */ -void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, - void *p_bio, - mbedtls_ssl_send_t *f_send, - mbedtls_ssl_recv_t *f_recv, - mbedtls_ssl_recv_timeout_t *f_recv_timeout ); - -/** - * \brief Set the timeout period for mbedtls_ssl_read() - * (Default: no timeout.) - * - * \param conf SSL configuration context - * \param timeout Timeout value in milliseconds. - * Use 0 for no timeout (default). - * - * \note With blocking I/O, this will only work if a non-NULL - * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). - * With non-blocking I/O, this will only work if timer - * callbacks were set with \c mbedtls_ssl_set_timer_cb(). - * - * \note With non-blocking I/O, you may also skip this function - * altogether and handle timeouts at the application layer. - */ -void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); - -/** - * \brief Set the timer callbacks (Mandatory for DTLS.) - * - * \param ssl SSL context - * \param p_timer parameter (context) shared by timer callbacks - * \param f_set_timer set timer callback - * \param f_get_timer get timer callback. Must return: - * - * \note See the documentation of \c mbedtls_ssl_set_timer_t and - * \c mbedtls_ssl_get_timer_t for the conventions this pair of - * callbacks must follow. - * - * \note On some platforms, timing.c provides - * \c mbedtls_timing_set_delay() and - * \c mbedtls_timing_get_delay() that are suitable for using - * here, except if using an event-driven style. - * - * \note See also the "DTLS tutorial" article in our knowledge base. - * https://tls.mbed.org/kb/how-to/dtls-tutorial - */ -void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, - void *p_timer, - mbedtls_ssl_set_timer_t *f_set_timer, - mbedtls_ssl_get_timer_t *f_get_timer ); - -/** - * \brief Callback type: generate and write session ticket - * - * \note This describes what a callback implementation should do. - * This callback should generate an encrypted and - * authenticated ticket for the session and write it to the - * output buffer. Here, ticket means the opaque ticket part - * of the NewSessionTicket structure of RFC 5077. - * - * \param p_ticket Context for the callback - * \param session SSL session to be written in the ticket - * \param start Start of the output buffer - * \param end End of the output buffer - * \param tlen On exit, holds the length written - * \param lifetime On exit, holds the lifetime of the ticket in seconds - * - * \return 0 if successful, or - * a specific MBEDTLS_ERR_XXX code. - */ -typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, - const mbedtls_ssl_session *session, - unsigned char *start, - const unsigned char *end, - size_t *tlen, - uint32_t *lifetime ); - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -/** - * \brief Callback type: Export key block and master secret - * - * \note This is required for certain uses of TLS, e.g. EAP-TLS - * (RFC 5216) and Thread. The key pointers are ephemeral and - * therefore must not be stored. The master secret and keys - * should not be used directly except as an input to a key - * derivation function. - * - * \param p_expkey Context for the callback - * \param ms Pointer to master secret (fixed length: 48 bytes) - * \param kb Pointer to key block, see RFC 5246 section 6.3 - * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). - * \param maclen MAC length - * \param keylen Key length - * \param ivlen IV length - * - * \return 0 if successful, or - * a specific MBEDTLS_ERR_XXX code. - */ -typedef int mbedtls_ssl_export_keys_t( void *p_expkey, - const unsigned char *ms, - const unsigned char *kb, - size_t maclen, - size_t keylen, - size_t ivlen ); -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ - -/** - * \brief Callback type: parse and load session ticket - * - * \note This describes what a callback implementation should do. - * This callback should parse a session ticket as generated - * by the corresponding mbedtls_ssl_ticket_write_t function, - * and, if the ticket is authentic and valid, load the - * session. - * - * \note The implementation is allowed to modify the first len - * bytes of the input buffer, eg to use it as a temporary - * area for the decrypted ticket contents. - * - * \param p_ticket Context for the callback - * \param session SSL session to be loaded - * \param buf Start of the buffer containing the ticket - * \param len Length of the ticket. - * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or - * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or - * any other non-zero code for other failures. - */ -typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, - mbedtls_ssl_session *session, - unsigned char *buf, - size_t len ); - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Configure SSL session ticket callbacks (server only). - * (Default: none.) - * - * \note On server, session tickets are enabled by providing - * non-NULL callbacks. - * - * \note On client, use \c mbedtls_ssl_conf_session_tickets(). - * - * \param conf SSL configuration context - * \param f_ticket_write Callback for writing a ticket - * \param f_ticket_parse Callback for parsing a ticket - * \param p_ticket Context shared by the two callbacks - */ -void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, - mbedtls_ssl_ticket_write_t *f_ticket_write, - mbedtls_ssl_ticket_parse_t *f_ticket_parse, - void *p_ticket ); -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -/** - * \brief Configure key export callback. - * (Default: none.) - * - * \note See \c mbedtls_ssl_export_keys_t. - * - * \param conf SSL configuration context - * \param f_export_keys Callback for exporting keys - * \param p_export_keys Context for the callback - */ -void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, - mbedtls_ssl_export_keys_t *f_export_keys, - void *p_export_keys ); -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ - -/** - * \brief Callback type: generate a cookie - * - * \param ctx Context for the callback - * \param p Buffer to write to, - * must be updated to point right after the cookie - * \param end Pointer to one past the end of the output buffer - * \param info Client ID info that was passed to - * \c mbedtls_ssl_set_client_transport_id() - * \param ilen Length of info in bytes - * - * \return The callback must return 0 on success, - * or a negative error code. - */ -typedef int mbedtls_ssl_cookie_write_t( void *ctx, - unsigned char **p, unsigned char *end, - const unsigned char *info, size_t ilen ); - -/** - * \brief Callback type: verify a cookie - * - * \param ctx Context for the callback - * \param cookie Cookie to verify - * \param clen Length of cookie - * \param info Client ID info that was passed to - * \c mbedtls_ssl_set_client_transport_id() - * \param ilen Length of info in bytes - * - * \return The callback must return 0 if cookie is valid, - * or a negative error code. - */ -typedef int mbedtls_ssl_cookie_check_t( void *ctx, - const unsigned char *cookie, size_t clen, - const unsigned char *info, size_t ilen ); - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Register callbacks for DTLS cookies - * (Server only. DTLS only.) - * - * Default: dummy callbacks that fail, in order to force you to - * register working callbacks (and initialize their context). - * - * To disable HelloVerifyRequest, register NULL callbacks. - * - * \warning Disabling hello verification allows your server to be used - * for amplification in DoS attacks against other hosts. - * Only disable if you known this can't happen in your - * particular environment. - * - * \note See comments on \c mbedtls_ssl_handshake() about handling - * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected - * on the first handshake attempt when this is enabled. - * - * \note This is also necessary to handle client reconnection from - * the same port as described in RFC 6347 section 4.2.8 (only - * the variant with cookies is supported currently). See - * comments on \c mbedtls_ssl_read() for details. - * - * \param conf SSL configuration - * \param f_cookie_write Cookie write callback - * \param f_cookie_check Cookie check callback - * \param p_cookie Context for both callbacks - */ -void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie ); - -/** - * \brief Set client's transport-level identification info. - * (Server only. DTLS only.) - * - * This is usually the IP address (and port), but could be - * anything identify the client depending on the underlying - * network stack. Used for HelloVerifyRequest with DTLS. - * This is *not* used to route the actual packets. - * - * \param ssl SSL context - * \param info Transport-level info identifying the client (eg IP + port) - * \param ilen Length of info in bytes - * - * \note An internal copy is made, so the info buffer can be reused. - * - * \return 0 on success, - * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, - * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. - */ -int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, - const unsigned char *info, - size_t ilen ); - -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -/** - * \brief Enable or disable anti-replay protection for DTLS. - * (DTLS only, no effect on TLS.) - * Default: enabled. - * - * \param conf SSL configuration - * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. - * - * \warning Disabling this is a security risk unless the application - * protocol handles duplicated packets in a safe way. You - * should not disable this without careful consideration. - * However, if your application already detects duplicated - * packets and needs information about them to adjust its - * transmission strategy, then you'll want to disable this. - */ -void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) -/** - * \brief Set a limit on the number of records with a bad MAC - * before terminating the connection. - * (DTLS only, no effect on TLS.) - * Default: 0 (disabled). - * - * \param conf SSL configuration - * \param limit Limit, or 0 to disable. - * - * \note If the limit is N, then the connection is terminated when - * the Nth non-authentic record is seen. - * - * \note Records with an invalid header are not counted, only the - * ones going through the authentication-decryption phase. - * - * \note This is a security trade-off related to the fact that it's - * often relatively easy for an active attacker ot inject UDP - * datagrams. On one hand, setting a low limit here makes it - * easier for such an attacker to forcibly terminated a - * connection. On the other hand, a high limit or no limit - * might make us waste resources checking authentication on - * many bogus packets. - */ -void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/** - * \brief Set retransmit timeout values for the DTLS handshake. - * (DTLS only, no effect on TLS.) - * - * \param conf SSL configuration - * \param min Initial timeout value in milliseconds. - * Default: 1000 (1 second). - * \param max Maximum timeout value in milliseconds. - * Default: 60000 (60 seconds). - * - * \note Default values are from RFC 6347 section 4.2.4.1. - * - * \note The 'min' value should typically be slightly above the - * expected round-trip time to your peer, plus whatever time - * it takes for the peer to process the message. For example, - * if your RTT is about 600ms and you peer needs up to 1s to - * do the cryptographic operations in the handshake, then you - * should set 'min' slightly above 1600. Lower values of 'min' - * might cause spurious resends which waste network resources, - * while larger value of 'min' will increase overall latency - * on unreliable network links. - * - * \note The more unreliable your network connection is, the larger - * your max / min ratio needs to be in order to achieve - * reliable handshakes. - * - * \note Messages are retransmitted up to log2(ceil(max/min)) times. - * For example, if min = 1s and max = 5s, the retransmit plan - * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> - * resend ... 5s -> give up and return a timeout error. - */ -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -#if defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Set the session cache callbacks (server-side only) - * If not set, no session resuming is done (except if session - * tickets are enabled too). - * - * The session cache has the responsibility to check for stale - * entries based on timeout. See RFC 5246 for recommendations. - * - * Warning: session.peer_cert is cleared by the SSL/TLS layer on - * connection shutdown, so do not cache the pointer! Either set - * it to NULL or make a full copy of the certificate. - * - * The get callback is called once during the initial handshake - * to enable session resuming. The get function has the - * following parameters: (void *parameter, mbedtls_ssl_session *session) - * If a valid entry is found, it should fill the master of - * the session object with the cached values and return 0, - * return 1 otherwise. Optionally peer_cert can be set as well - * if it is properly present in cache entry. - * - * The set callback is called once during the initial handshake - * to enable session resuming after the entire handshake has - * been finished. The set function has the following parameters: - * (void *parameter, const mbedtls_ssl_session *session). The function - * should create a cache entry for future retrieval based on - * the data in the session structure and should keep in mind - * that the mbedtls_ssl_session object presented (and all its referenced - * data) is cleared by the SSL/TLS layer when the connection is - * terminated. It is recommended to add metadata to determine if - * an entry is still valid in the future. Return 0 if - * successfully cached, return 1 otherwise. - * - * \param conf SSL configuration - * \param p_cache parmater (context) for both callbacks - * \param f_get_cache session get callback - * \param f_set_cache session set callback - */ -void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, - void *p_cache, - int (*f_get_cache)(void *, mbedtls_ssl_session *), - int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Request resumption of session (client-side only) - * Session data is copied from presented session structure. - * - * \param ssl SSL context - * \param session session context - * - * \return 0 if successful, - * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid - * - * \sa mbedtls_ssl_get_session() - */ -int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); -#endif /* MBEDTLS_SSL_CLI_C */ - -/** - * \brief Set the list of allowed ciphersuites and the preference - * order. First in the list has the highest preference. - * (Overrides all version-specific lists) - * - * The ciphersuites array is not copied, and must remain - * valid for the lifetime of the ssl_config. - * - * Note: The server uses its own preferences - * over the preference of the client unless - * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! - * - * \param conf SSL configuration - * \param ciphersuites 0-terminated list of allowed ciphersuites - */ -void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, - const int *ciphersuites ); - -/** - * \brief Set the list of allowed ciphersuites and the - * preference order for a specific version of the protocol. - * (Only useful on the server side) - * - * The ciphersuites array is not copied, and must remain - * valid for the lifetime of the ssl_config. - * - * \param conf SSL configuration - * \param ciphersuites 0-terminated list of allowed ciphersuites - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 - * supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) - * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 - * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 - */ -void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, - const int *ciphersuites, - int major, int minor ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Set the X.509 security profile used for verification - * - * \note The restrictions are enforced for all certificates in the - * chain. However, signatures in the handshake are not covered - * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). - * - * \param conf SSL configuration - * \param profile Profile to use - */ -void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, - const mbedtls_x509_crt_profile *profile ); - -/** - * \brief Set the data required to verify peer certificate - * - * \param conf SSL configuration - * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) - * \param ca_crl trusted CA CRLs - */ -void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ); - -/** - * \brief Set own certificate chain and private key - * - * \note own_cert should contain in order from the bottom up your - * certificate chain. The top certificate (self-signed) - * can be omitted. - * - * \note On server, this function can be called multiple times to - * provision more than one cert/key pair (eg one ECDSA, one - * RSA with SHA-256, one RSA with SHA-1). An adequate - * certificate will be selected according to the client's - * advertised capabilities. In case mutliple certificates are - * adequate, preference is given to the one set by the first - * call to this function, then second, etc. - * - * \note On client, only the first call has any effect. That is, - * only one client certificate can be provisioned. The - * server's preferences in its CertficateRequest message will - * be ignored and our only cert will be sent regardless of - * whether it matches those preferences - the server can then - * decide what it wants to do with it. - * - * \param conf SSL configuration - * \param own_cert own public certificate chain - * \param pk_key own private key - * - * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -/** - * \brief Set the Pre Shared Key (PSK) and the expected identity name - * - * \note This is mainly useful for clients. Servers will usually - * want to use \c mbedtls_ssl_conf_psk_cb() instead. - * - * \note Currently clients can only register one pre-shared key. - * In other words, the servers' identity hint is ignored. - * Support for setting multiple PSKs on clients and selecting - * one based on the identity hint is not a planned feature but - * feedback is welcomed. - * - * \param conf SSL configuration - * \param psk pointer to the pre-shared key - * \param psk_len pre-shared key length - * \param psk_identity pointer to the pre-shared key identity - * \param psk_identity_len identity key length - * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, - const unsigned char *psk, size_t psk_len, - const unsigned char *psk_identity, size_t psk_identity_len ); - - -/** - * \brief Set the Pre Shared Key (PSK) for the current handshake - * - * \note This should only be called inside the PSK callback, - * ie the function passed to \c mbedtls_ssl_conf_psk_cb(). - * - * \param ssl SSL context - * \param psk pointer to the pre-shared key - * \param psk_len pre-shared key length - * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, - const unsigned char *psk, size_t psk_len ); - -/** - * \brief Set the PSK callback (server-side only). - * - * If set, the PSK callback is called for each - * handshake where a PSK ciphersuite was negotiated. - * The caller provides the identity received and wants to - * receive the actual PSK data and length. - * - * The callback has the following parameters: (void *parameter, - * mbedtls_ssl_context *ssl, const unsigned char *psk_identity, - * size_t identity_len) - * If a valid PSK identity is found, the callback should use - * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the - * correct PSK and return 0. - * Any other return value will result in a denied PSK identity. - * - * \note If you set a PSK callback using this function, then you - * don't need to set a PSK key and identity using - * \c mbedtls_ssl_conf_psk(). - * - * \param conf SSL configuration - * \param f_psk PSK identity function - * \param p_psk PSK identity parameter - */ -void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_psk ); -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Set the Diffie-Hellman public P and G values, - * read as hexadecimal strings (server-side only) - * (Default: MBEDTLS_DHM_RFC5114_MODP_2048_[PG]) - * - * \param conf SSL configuration - * \param dhm_P Diffie-Hellman-Merkle modulus - * \param dhm_G Diffie-Hellman-Merkle generator - * - * \return 0 if successful - */ -int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ); - -/** - * \brief Set the Diffie-Hellman public P and G values, - * read from existing context (server-side only) - * - * \param conf SSL configuration - * \param dhm_ctx Diffie-Hellman-Merkle context - * - * \return 0 if successful - */ -int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); -#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Set the minimum length for Diffie-Hellman parameters. - * (Client-side only.) - * (Default: 1024 bits.) - * - * \param conf SSL configuration - * \param bitlen Minimum bit length of the DHM prime - */ -void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, - unsigned int bitlen ); -#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_ECP_C) -/** - * \brief Set the allowed curves in order of preference. - * (Default: all defined curves.) - * - * On server: this only affects selection of the ECDHE curve; - * the curves used for ECDH and ECDSA are determined by the - * list of available certificates instead. - * - * On client: this affects the list of curves offered for any - * use. The server can override our preference order. - * - * Both sides: limits the set of curves accepted for use in - * ECDHE and in the peer's end-entity certificate. - * - * \note This has no influence on which curves are allowed inside the - * certificate chains, see \c mbedtls_ssl_conf_cert_profile() - * for that. For the end-entity certificate however, the key - * will be accepted only if it is allowed both by this list - * and by the cert profile. - * - * \note This list should be ordered by decreasing preference - * (preferred curve first). - * - * \param conf SSL configuration - * \param curves Ordered list of allowed curves, - * terminated by MBEDTLS_ECP_DP_NONE. - */ -void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, - const mbedtls_ecp_group_id *curves ); -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -/** - * \brief Set the allowed hashes for signatures during the handshake. - * (Default: all available hashes except MD5.) - * - * \note This only affects which hashes are offered and can be used - * for signatures during the handshake. Hashes for message - * authentication and the TLS PRF are controlled by the - * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes - * used for certificate signature are controlled by the - * verification profile, see \c mbedtls_ssl_conf_cert_profile(). - * - * \note This list should be ordered by decreasing preference - * (preferred hash first). - * - * \param conf SSL configuration - * \param hashes Ordered list of allowed signature hashes, - * terminated by \c MBEDTLS_MD_NONE. - */ -void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, - const int *hashes ); -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Set the hostname to check against the received server - * certificate. It sets the ServerName TLS extension too, - * if the extension is enabled. - * (client-side only) - * - * \param ssl SSL context - * \param hostname the server hostname - * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -/** - * \brief Set own certificate and key for the current handshake - * - * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within - * the SNI callback. - * - * \param ssl SSL context - * \param own_cert own public certificate chain - * \param pk_key own private key - * - * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ); - -/** - * \brief Set the data required to verify peer certificate for the - * current handshake - * - * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within - * the SNI callback. - * - * \param ssl SSL context - * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) - * \param ca_crl trusted CA CRLs - */ -void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ); - -/** - * \brief Set authmode for the current handshake. - * - * \note Same as \c mbedtls_ssl_conf_authmode() but for use within - * the SNI callback. - * - * \param ssl SSL context - * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or - * MBEDTLS_SSL_VERIFY_REQUIRED - */ -void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, - int authmode ); - -/** - * \brief Set server side ServerName TLS extension callback - * (optional, server-side only). - * - * If set, the ServerName callback is called whenever the - * server receives a ServerName TLS extension from the client - * during a handshake. The ServerName callback has the - * following parameters: (void *parameter, mbedtls_ssl_context *ssl, - * const unsigned char *hostname, size_t len). If a suitable - * certificate is found, the callback must set the - * certificate(s) and key(s) to use with \c - * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), - * and may optionally adjust the CA and associated CRL with \c - * mbedtls_ssl_set_hs_ca_chain() as well as the client - * authentication mode with \c mbedtls_ssl_set_hs_authmode(), - * then must return 0. If no matching name is found, the - * callback must either set a default cert, or - * return non-zero to abort the handshake at this point. - * - * \param conf SSL configuration - * \param f_sni verification function - * \param p_sni verification parameter - */ -void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, - int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_sni ); -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -/** - * \brief Set the EC J-PAKE password for current handshake. - * - * \note An internal copy is made, and destroyed as soon as the - * handshake is completed, or when the SSL context is reset or - * freed. - * - * \note The SSL context needs to be already set up. The right place - * to call this function is between \c mbedtls_ssl_setup() or - * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). - * - * \param ssl SSL context - * \param pw EC J-PAKE password (pre-shared secret) - * \param pw_len length of pw in bytes - * - * \return 0 on success, or a negative error code. - */ -int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, - const unsigned char *pw, - size_t pw_len ); -#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_ALPN) -/** - * \brief Set the supported Application Layer Protocols. - * - * \param conf SSL configuration - * \param protos Pointer to a NULL-terminated list of supported protocols, - * in decreasing preference order. The pointer to the list is - * recorded by the library for later reference as required, so - * the lifetime of the table must be atleast as long as the - * lifetime of the SSL configuration structure. - * - * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. - */ -int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); - -/** - * \brief Get the name of the negotiated Application Layer Protocol. - * This function should be called after the handshake is - * completed. - * - * \param ssl SSL context - * - * \return Protcol name, or NULL if no protocol was negotiated. - */ -const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_SSL_ALPN */ - -/** - * \brief Set the maximum supported version sent from the client side - * and/or accepted at the server side - * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) - * - * \note This ignores ciphersuites from higher versions. - * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and - * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 - * - * \param conf SSL configuration - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) - */ -void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); - -/** - * \brief Set the minimum accepted SSL/TLS protocol version - * (Default: TLS 1.0) - * - * \note Input outside of the SSL_MAX_XXXXX_VERSION and - * SSL_MIN_XXXXX_VERSION range is ignored. - * - * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. - * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and - * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 - * - * \param conf SSL configuration - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) - */ -void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Set the fallback flag (client-side only). - * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). - * - * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback - * connection, that is a connection with max_version set to a - * lower value than the value you're willing to use. Such - * fallback connections are not recommended but are sometimes - * necessary to interoperate with buggy (version-intolerant) - * servers. - * - * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for - * non-fallback connections! This would appear to work for a - * while, then cause failures when the server is upgraded to - * support a newer TLS version. - * - * \param conf SSL configuration - * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK - */ -void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); -#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -/** - * \brief Enable or disable Encrypt-then-MAC - * (Default: MBEDTLS_SSL_ETM_ENABLED) - * - * \note This should always be enabled, it is a security - * improvement, and should not cause any interoperability - * issue (used only if the peer supports it too). - * - * \param conf SSL configuration - * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED - */ -void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -/** - * \brief Enable or disable Extended Master Secret negotiation. - * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) - * - * \note This should always be enabled, it is a security fix to the - * protocol, and should not cause any interoperability issue - * (used only if the peer supports it too). - * - * \param conf SSL configuration - * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED - */ -void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_ARC4_C) -/** - * \brief Disable or enable support for RC4 - * (Default: MBEDTLS_SSL_ARC4_DISABLED) - * - * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 - * for security reasons. Use at your own risk. - * - * \note This function is deprecated and will likely be removed in - * a future version of the library. - * RC4 is disabled by default at compile time and needs to be - * actively enabled for use with legacy systems. - * - * \param conf SSL configuration - * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED - */ -void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -/** - * \brief Set the maximum fragment length to emit and/or negotiate - * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) - * (Server: set maximum fragment length to emit, - * usually negotiated by the client during handshake - * (Client: set maximum fragment length to emit *and* - * negotiate with the server during handshake) - * - * \param conf SSL configuration - * \param mfl_code Code for maximum fragment length (allowed values: - * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, - * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) - * - * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA - */ -int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -/** - * \brief Activate negotiation of truncated HMAC - * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) - * - * \param conf SSL configuration - * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or - * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) - */ -void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -/** - * \brief Enable / Disable 1/n-1 record splitting - * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) - * - * \note Only affects SSLv3 and TLS 1.0, not higher versions. - * Does not affect non-CBC ciphersuites in any version. - * - * \param conf SSL configuration - * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or - * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED - */ -void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Enable / Disable session tickets (client only). - * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) - * - * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). - * - * \param conf SSL configuration - * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or - * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) - */ -void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -/** - * \brief Enable / Disable renegotiation support for connection when - * initiated by peer - * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) - * - * \warning It is recommended to always disable renegotation unless you - * know you need it and you know what you're doing. In the - * past, there have been several issues associated with - * renegotiation or a poor understanding of its properties. - * - * \note Server-side, enabling renegotiation also makes the server - * susceptible to a resource DoS by a malicious client. - * - * \param conf SSL configuration - * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or - * MBEDTLS_SSL_RENEGOTIATION_DISABLED) - */ -void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/** - * \brief Prevent or allow legacy renegotiation. - * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) - * - * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to - * be established even if the peer does not support - * secure renegotiation, but does not allow renegotiation - * to take place if not secure. - * (Interoperable and secure option) - * - * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations - * with non-upgraded peers. Allowing legacy renegotiation - * makes the connection vulnerable to specific man in the - * middle attacks. (See RFC 5746) - * (Most interoperable and least secure option) - * - * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections - * if peer does not support secure renegotiation. Results - * in interoperability issues with non-upgraded peers - * that do not support renegotiation altogether. - * (Most secure option, interoperability issues) - * - * \param conf SSL configuration - * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, - * SSL_ALLOW_LEGACY_RENEGOTIATION or - * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) - */ -void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -/** - * \brief Enforce renegotiation requests. - * (Default: enforced, max_records = 16) - * - * When we request a renegotiation, the peer can comply or - * ignore the request. This function allows us to decide - * whether to enforce our renegotiation requests by closing - * the connection if the peer doesn't comply. - * - * However, records could already be in transit from the peer - * when the request is emitted. In order to increase - * reliability, we can accept a number of records before the - * expected handshake records. - * - * The optimal value is highly dependent on the specific usage - * scenario. - * - * \note With DTLS and server-initiated renegotiation, the - * HelloRequest is retransmited every time mbedtls_ssl_read() times - * out or receives Application Data, until: - * - max_records records have beens seen, if it is >= 0, or - * - the number of retransmits that would happen during an - * actual handshake has been reached. - * Please remember the request might be lost a few times - * if you consider setting max_records to a really low value. - * - * \warning On client, the grace period can only happen during - * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() - * which always behave as if max_record was 0. The reason is, - * if we receive application data from the server, we need a - * place to write it, which only happens during mbedtls_ssl_read(). - * - * \param conf SSL configuration - * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to - * enforce renegotiation, or a non-negative value to enforce - * it but allow for a grace period of max_records records. - */ -void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); - -/** - * \brief Set record counter threshold for periodic renegotiation. - * (Default: 2^48 - 1) - * - * Renegotiation is automatically triggered when a record - * counter (outgoing or ingoing) crosses the defined - * threshold. The default value is meant to prevent the - * connection from being closed when the counter is about to - * reached its maximal value (it is not allowed to wrap). - * - * Lower values can be used to enforce policies such as "keys - * must be refreshed every N packets with cipher X". - * - * The renegotiation period can be disabled by setting - * conf->disable_renegotiation to - * MBEDTLS_SSL_RENEGOTIATION_DISABLED. - * - * \note When the configured transport is - * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation - * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, - * the maximum renegotiation period is 2^64 - 1. - * - * \param conf SSL configuration - * \param period The threshold value: a big-endian 64-bit number. - */ -void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, - const unsigned char period[8] ); -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/** - * \brief Return the number of data bytes available to read - * - * \param ssl SSL context - * - * \return how many bytes are available in the read buffer - */ -size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); - -/** - * \brief Return the result of the certificate verification - * - * \param ssl SSL context - * - * \return 0 if successful, - * -1 if result is not available (eg because the handshake was - * aborted too early), or - * a combination of BADCERT_xxx and BADCRL_xxx flags, see - * x509.h - */ -uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); - -/** - * \brief Return the name of the current ciphersuite - * - * \param ssl SSL context - * - * \return a string containing the ciphersuite name - */ -const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); - -/** - * \brief Return the current SSL version (SSLv3/TLSv1/etc) - * - * \param ssl SSL context - * - * \return a string containing the SSL version - */ -const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); - -/** - * \brief Return the (maximum) number of bytes added by the record - * layer: header + encryption/MAC overhead (inc. padding) - * - * \param ssl SSL context - * - * \return Current maximum record expansion in bytes, or - * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is - * enabled, which makes expansion much less predictable - */ -int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -/** - * \brief Return the maximum fragment length (payload, in bytes). - * This is the value negotiated with peer if any, - * or the locally configured value. - * - * \note With DTLS, \c mbedtls_ssl_write() will return an error if - * called with a larger length value. - * With TLS, \c mbedtls_ssl_write() will fragment the input if - * necessary and return the number of bytes written; it is up - * to the caller to call \c mbedtls_ssl_write() again in - * order to send the remaining bytes if any. - * - * \param ssl SSL context - * - * \return Current maximum fragment length. - */ -size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Return the peer certificate from the current connection - * - * Note: Can be NULL in case no certificate was sent during - * the handshake. Different calls for the same connection can - * return the same or different pointers for the same - * certificate and even a different certificate altogether. - * The peer cert CAN change in a single connection if - * renegotiation is performed. - * - * \param ssl SSL context - * - * \return the current peer certificate - */ -const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Save session in order to resume it later (client-side only) - * Session data is copied to presented session structure. - * - * \warning Currently, peer certificate is lost in the operation. - * - * \param ssl SSL context - * \param session session context - * - * \return 0 if successful, - * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid - * - * \sa mbedtls_ssl_set_session() - */ -int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); -#endif /* MBEDTLS_SSL_CLI_C */ - -/** - * \brief Perform the SSL handshake - * - * \param ssl SSL context - * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or - * a specific SSL error code. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * - * \note If DTLS is in use, then you may choose to handle - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging - * purposes, as it is an expected return value rather than an - * actual error, but you still need to reset/free the context. - */ -int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); - -/** - * \brief Perform a single step of the SSL handshake - * - * \note The state of the context (ssl->state) will be at - * the next state after execution of this function. Do not - * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * - * \param ssl SSL context - * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * a specific SSL error code. - */ -int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -/** - * \brief Initiate an SSL renegotiation on the running connection. - * Client: perform the renegotiation right now. - * Server: request renegotiation, which will be performed - * during the next call to mbedtls_ssl_read() if honored by - * client. - * - * \param ssl SSL context - * - * \return 0 if successful, or any mbedtls_ssl_handshake() return - * value. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - */ -int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/** - * \brief Read at most 'len' application data bytes - * - * \param ssl SSL context - * \param buf buffer that will hold the data - * \param len maximum number of bytes to read - * - * \return the number of bytes read, or - * 0 for EOF, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or - * another negative error code. - * - * \note If this function returns something other than a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * - * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT - * (which can only happen server-side), it means that a client - * is initiating a new connection using the same source port. - * You can either treat that as a connection close and wait - * for the client to resend a ClientHello, or directly - * continue with \c mbedtls_ssl_handshake() with the same - * context (as it has beeen reset internally). Either way, you - * should make sure this is seen by the application as a new - * connection: application state, if any, should be reset, and - * most importantly the identity of the client must be checked - * again. WARNING: not validating the identity of the client - * again, or not transmitting the new identity to the - * application layer, would allow authentication bypass! - */ -int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); - -/** - * \brief Try to write exactly 'len' application data bytes - * - * \warning This function will do partial writes in some cases. If the - * return value is non-negative but less than length, the - * function must be called again with updated arguments: - * buf + ret, len - ret (if ret is the return value) until - * it returns a value equal to the last 'len' argument. - * - * \param ssl SSL context - * \param buf buffer holding the data - * \param len how many bytes must be written - * - * \return the number of bytes actually written (may be less than len), - * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, - * or another negative error code. - * - * \note If this function returns something other than a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * - * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, - * it must be called later with the *same* arguments, - * until it returns a positive value. - * - * \note If the requested length is greater than the maximum - * fragment length (either the built-in limit or the one set - * or negotiated with the peer), then: - * - with TLS, less bytes than requested are written. - * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. - * \c mbedtls_ssl_get_max_frag_len() may be used to query the - * active maximum fragment length. - */ -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); - -/** - * \brief Send an alert message - * - * \param ssl SSL context - * \param level The alert level of the message - * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) - * \param message The alert message (SSL_ALERT_MSG_*) - * - * \return 0 if successful, or a specific SSL error code. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - */ -int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, - unsigned char level, - unsigned char message ); -/** - * \brief Notify the peer that the connection is being closed - * - * \param ssl SSL context - * - * \return 0 if successful, or a specific SSL error code. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - */ -int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); - -/** - * \brief Free referenced items in an SSL context and clear memory - * - * \param ssl SSL context - */ -void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); - -/** - * \brief Initialize an SSL configuration context - * Just makes the context ready for - * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). - * - * \note You need to call mbedtls_ssl_config_defaults() unless you - * manually set all of the relevent fields yourself. - * - * \param conf SSL configuration context - */ -void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); - -/** - * \brief Load reasonnable default SSL configuration values. - * (You need to call mbedtls_ssl_config_init() first.) - * - * \param conf SSL configuration context - * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER - * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or - * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS - * \param preset a MBEDTLS_SSL_PRESET_XXX value - * - * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. - * - * \return 0 if successful, or - * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. - */ -int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, - int endpoint, int transport, int preset ); - -/** - * \brief Free an SSL configuration context - * - * \param conf SSL configuration context - */ -void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); - -/** - * \brief Initialize SSL session structure - * - * \param session SSL session - */ -void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); - -/** - * \brief Free referenced items in an SSL session including the - * peer certificate and clear memory - * - * \param session SSL session - */ -void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); - -#ifdef __cplusplus -} -#endif - -#endif /* ssl.h */ diff --git a/components/security/mbedtls/include/mbedtls/ssl_cache.h b/components/security/mbedtls/include/mbedtls/ssl_cache.h deleted file mode 100644 index 3734bb72..00000000 --- a/components/security/mbedtls/include/mbedtls/ssl_cache.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - * \file ssl_cache.h - * - * \brief SSL session cache implementation - * - * 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) - */ -#ifndef MBEDTLS_SSL_CACHE_H -#define MBEDTLS_SSL_CACHE_H - -#include "ssl.h" - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) -#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ -#endif - -#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) -#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ -#endif - -/* \} name SECTION: Module settings */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; -typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; - -/** - * \brief This structure is used for storing cache entries - */ -struct mbedtls_ssl_cache_entry -{ -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t timestamp; /*!< entry timestamp */ -#endif - mbedtls_ssl_session session; /*!< entry session */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ -#endif - mbedtls_ssl_cache_entry *next; /*!< chain pointer */ -}; - -/** - * \brief Cache context - */ -struct mbedtls_ssl_cache_context -{ - mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ - int timeout; /*!< cache entry timeout */ - int max_entries; /*!< maximum entries */ -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< mutex */ -#endif -}; - -/** - * \brief Initialize an SSL cache context - * - * \param cache SSL cache context - */ -void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); - -/** - * \brief Cache get callback implementation - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param data SSL cache context - * \param session session to retrieve entry for - */ -int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ); - -/** - * \brief Cache set callback implementation - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param data SSL cache context - * \param session session to store entry for - */ -int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ); - -#if defined(MBEDTLS_HAVE_TIME) -/** - * \brief Set the cache timeout - * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) - * - * A timeout of 0 indicates no timeout. - * - * \param cache SSL cache context - * \param timeout cache entry timeout in seconds - */ -void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); -#endif /* MBEDTLS_HAVE_TIME */ - -/** - * \brief Set the maximum number of cache entries - * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) - * - * \param cache SSL cache context - * \param max cache entry maximum - */ -void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); - -/** - * \brief Free referenced items in a cache context and clear memory - * - * \param cache SSL cache context - */ -void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_cache.h */ diff --git a/components/security/mbedtls/include/mbedtls/ssl_ciphersuites.h b/components/security/mbedtls/include/mbedtls/ssl_ciphersuites.h deleted file mode 100644 index deaaa375..00000000 --- a/components/security/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ /dev/null @@ -1,321 +0,0 @@ -/** - * \file ssl_ciphersuites.h - * - * \brief SSL Ciphersuites for mbed TLS - * - * 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) - */ -#ifndef MBEDTLS_SSL_CIPHERSUITES_H -#define MBEDTLS_SSL_CIPHERSUITES_H - -#include "pk.h" -#include "cipher.h" -#include "md.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Supported ciphersuites (Official IANA names) - */ -#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ -#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ - -#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 -#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 -#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A - -#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 - -#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ -#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ -#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ -#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F - -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 -#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 - -#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ -#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 - -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 - -#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A -#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B -#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C -#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D - -#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E -#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 - -#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 -#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 - -#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ - -#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ - -#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE -#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF -#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ -#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ - -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 -#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ -#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ - -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 -#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ -#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ - -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ - -#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ - -#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ - -#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ - -#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ - -#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 -#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 -#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 -#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 -#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 -#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 -#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ - -#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ -/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ - -#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ - -/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. - * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below - */ -typedef enum { - MBEDTLS_KEY_EXCHANGE_NONE = 0, - MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_KEY_EXCHANGE_ECJPAKE, -} mbedtls_key_exchange_type_t; - -/* Key exchanges using a certificate */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED -#endif - -/* Key exchanges using a PSK */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED -#endif - -/* Key exchanges using a ECDHE */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED -#endif - -typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; - -#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ -#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, - eg for CCM_8 */ -#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ - -/** - * \brief This structure is used for storing ciphersuite information - */ -struct mbedtls_ssl_ciphersuite_t -{ - int id; - const char * name; - - mbedtls_cipher_type_t cipher; - mbedtls_md_type_t mac; - mbedtls_key_exchange_type_t key_exchange; - - int min_major_ver; - int min_minor_ver; - int max_major_ver; - int max_minor_ver; - - unsigned char flags; -}; - -const int *mbedtls_ssl_list_ciphersuites( void ); - -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); - -#if defined(MBEDTLS_PK_C) -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); -#endif - -int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); -int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_ciphersuites.h */ diff --git a/components/security/mbedtls/include/mbedtls/ssl_cookie.h b/components/security/mbedtls/include/mbedtls/ssl_cookie.h deleted file mode 100644 index 037e1c31..00000000 --- a/components/security/mbedtls/include/mbedtls/ssl_cookie.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * \file ssl_cookie.h - * - * \brief DTLS cookie callbacks implementation - * - * 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) - */ -#ifndef MBEDTLS_SSL_COOKIE_H -#define MBEDTLS_SSL_COOKIE_H - -#include "ssl.h" - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ -#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT -#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ -#endif - -/* \} name SECTION: Module settings */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Context for the default cookie functions. - */ -typedef struct -{ - mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ -#if !defined(MBEDTLS_HAVE_TIME) - unsigned long serial; /*!< serial number for expiration */ -#endif - unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, - or in number of tickets issued */ - -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} mbedtls_ssl_cookie_ctx; - -/** - * \brief Initialize cookie context - */ -void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); - -/** - * \brief Setup cookie context (generate keys) - */ -int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Set expiration delay for cookies - * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) - * - * \param ctx Cookie contex - * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies - * issued in the meantime. - * 0 to disable expiration (NOT recommended) - */ -void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); - -/** - * \brief Free cookie context - */ -void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); - -/** - * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t - */ -mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; - -/** - * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t - */ -mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_cookie.h */ diff --git a/components/security/mbedtls/include/mbedtls/ssl_internal.h b/components/security/mbedtls/include/mbedtls/ssl_internal.h deleted file mode 100644 index 668c0f56..00000000 --- a/components/security/mbedtls/include/mbedtls/ssl_internal.h +++ /dev/null @@ -1,500 +0,0 @@ -/** - * \file ssl_ticket.h - * - * \brief Internal functions shared by the SSL modules - * - * 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) - */ -#ifndef MBEDTLS_SSL_INTERNAL_H -#define MBEDTLS_SSL_INTERNAL_H - -#include "ssl.h" - -#if defined(MBEDTLS_MD5_C) -#include "md5.h" -#endif - -#if defined(MBEDTLS_SHA1_C) -#include "sha1.h" -#endif - -#if defined(MBEDTLS_SHA256_C) -#include "sha256.h" -#endif - -#if defined(MBEDTLS_SHA512_C) -#include "sha512.h" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#include "ecjpake.h" -#endif - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -/* Determine minimum supported version */ -#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -/* Determine maximum supported version */ -#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 -#else -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 -#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ -#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ -#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ - -/* - * DTLS retransmission states, see RFC 6347 4.2.4 - * - * The SENDING state is merged in PREPARING for initial sends, - * but is distinct for resends. - * - * Note: initial state is wrong for server, but is not used anyway. - */ -#define MBEDTLS_SSL_RETRANS_PREPARING 0 -#define MBEDTLS_SSL_RETRANS_SENDING 1 -#define MBEDTLS_SSL_RETRANS_WAITING 2 -#define MBEDTLS_SSL_RETRANS_FINISHED 3 - -/* - * Allow extra bytes for record, authentication and encryption overhead: - * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) - * and allow for a maximum of 1024 of compression expansion if - * enabled. - */ -#if defined(MBEDTLS_ZLIB_SUPPORT) -#define MBEDTLS_SSL_COMPRESSION_ADD 1024 -#else -#define MBEDTLS_SSL_COMPRESSION_ADD 0 -#endif - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC) -/* Ciphersuites using HMAC */ -#if defined(MBEDTLS_SHA512_C) -#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ -#elif defined(MBEDTLS_SHA256_C) -#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ -#else -#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ -#endif -#else -/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ -#define MBEDTLS_SSL_MAC_ADD 16 -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#define MBEDTLS_SSL_PADDING_ADD 256 -#else -#define MBEDTLS_SSL_PADDING_ADD 0 -#endif - -#define MBEDTLS_SSL_BUFFER_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ - + MBEDTLS_SSL_COMPRESSION_ADD \ - + 29 /* counter + header + IV */ \ - + MBEDTLS_SSL_MAC_ADD \ - + MBEDTLS_SSL_PADDING_ADD \ - ) - -/* - * TLS extension flags (for extensions with outgoing ServerHello content - * that need it (e.g. for RENEGOTIATION_INFO the server already knows because - * of state of the renegotiation flag, so no indicator is required) - */ -#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) -#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This structure contains the parameters only needed during handshake. - */ -struct mbedtls_ssl_handshake_params -{ - /* - * Handshake specific crypto variables - */ - int sig_alg; /*!< Hash algorithm for signature */ - int verify_sig_alg; /*!< Signature algorithm for verify */ -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ -#endif -#if defined(MBEDTLS_ECDH_C) - mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ -#if defined(MBEDTLS_SSL_CLI_C) - unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ - size_t ecjpake_cache_len; /*!< Length of cached data */ -#endif -#endif -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char *psk; /*!< PSK from the callback */ - size_t psk_len; /*!< Length of PSK from callback */ -#endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - int sni_authmode; /*!< authmode from SNI callback */ - mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ - mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ - mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ -#endif -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ - unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ - - unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie - Srv: unused */ - unsigned char verify_cookie_len; /*!< Cli: cookie length - Srv: flag for sending a cookie */ - - unsigned char *hs_msg; /*!< Reassembled handshake message */ - - uint32_t retransmit_timeout; /*!< Current value of timeout */ - unsigned char retransmit_state; /*!< Retransmission state */ - mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ - mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ - unsigned int in_flight_start_seq; /*!< Minimum message sequence in the - flight being received */ - mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for - resending messages */ - unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter - for resending messages */ -#endif - - /* - * Checksum contexts - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_context fin_md5; - mbedtls_sha1_context fin_sha1; -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_context fin_sha256; -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_context fin_sha512; -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); - void (*calc_verify)(mbedtls_ssl_context *, unsigned char *); - void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); - int (*tls_prf)(const unsigned char *, size_t, const char *, - const unsigned char *, size_t, - unsigned char *, size_t); - - size_t pmslen; /*!< premaster length */ - - unsigned char randbytes[64]; /*!< random bytes */ - unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; - /*!< premaster secret */ - - int resume; /*!< session resume indicator*/ - int max_major_ver; /*!< max. major version client*/ - int max_minor_ver; /*!< max. minor version client*/ - int cli_exts; /*!< client extension presence*/ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - int new_session_ticket; /*!< use NewSessionTicket? */ -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - int extended_ms; /*!< use Extended Master Secret? */ -#endif -}; - -/* - * This structure contains a full set of runtime transform parameters - * either in negotiation or active. - */ -struct mbedtls_ssl_transform -{ - /* - * Session specific crypto layer - */ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - /*!< Chosen cipersuite_info */ - unsigned int keylen; /*!< symmetric key length (bytes) */ - size_t minlen; /*!< min. ciphertext length */ - size_t ivlen; /*!< IV length */ - size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ - size_t maclen; /*!< MAC length */ - - unsigned char iv_enc[16]; /*!< IV (encryption) */ - unsigned char iv_dec[16]; /*!< IV (decryption) */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* Needed only for SSL v3.0 secret */ - unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ - unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - - mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ - mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ - - mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ - mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ - - /* - * Session specific compression layer - */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - z_stream ctx_deflate; /*!< compression context */ - z_stream ctx_inflate; /*!< decompression context */ -#endif -}; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/* - * List of certificate + private key pairs - */ -struct mbedtls_ssl_key_cert -{ - mbedtls_x509_crt *cert; /*!< cert */ - mbedtls_pk_context *key; /*!< private key */ - mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ -}; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * List of handshake messages kept around for resending - */ -struct mbedtls_ssl_flight_item -{ - unsigned char *p; /*!< message, including handshake headers */ - size_t len; /*!< length of p */ - unsigned char type; /*!< type of the message: handshake or CCS */ - mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ -}; -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - -/** - * \brief Free referenced items in an SSL transform context and clear - * memory - * - * \param transform SSL transform context - */ -void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); - -/** - * \brief Free referenced items in an SSL handshake context and clear - * memory - * - * \param handshake SSL handshake context - */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); - -int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); - -void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); - -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); - -void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); -#endif - -#if defined(MBEDTLS_PK_C) -unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); -mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); -#endif - -mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); -unsigned char mbedtls_ssl_hash_from_md_alg( int md ); -int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); - -#if defined(MBEDTLS_ECP_C) -int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, - mbedtls_md_type_t md ); -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_key_cert *key_cert; - - if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) - key_cert = ssl->handshake->key_cert; - else - key_cert = ssl->conf->key_cert; - - return( key_cert == NULL ? NULL : key_cert->key ); -} - -static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_key_cert *key_cert; - - if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) - key_cert = ssl->handshake->key_cert; - else - key_cert = ssl->conf->key_cert; - - return( key_cert == NULL ? NULL : key_cert->cert ); -} - -/* - * Check usage of a certificate wrt extensions: - * keyUsage, extendedKeyUsage (later), and nSCertType (later). - * - * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we - * check a cert we received from them)! - * - * Return 0 if everything is OK, -1 if not. - */ -int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, - const mbedtls_ssl_ciphersuite_t *ciphersuite, - int cert_endpoint, - uint32_t *flags ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -void mbedtls_ssl_write_version( int major, int minor, int transport, - unsigned char ver[2] ); -void mbedtls_ssl_read_version( int *major, int *minor, int transport, - const unsigned char ver[2] ); - -static inline size_t mbedtls_ssl_hdr_len( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 13 ); -#else - ((void) ssl); -#endif - return( 5 ); -} - -static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 12 ); -#else - ((void) ssl); -#endif - return( 4 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); -#endif - -/* Visible for testing purposes only */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); -#endif - -/* constant-time buffer comparison */ -static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) -{ - size_t i; - const unsigned char *A = (const unsigned char *) a; - const unsigned char *B = (const unsigned char *) b; - unsigned char diff = 0; - - for( i = 0; i < n; i++ ) - diff |= A[i] ^ B[i]; - - return( diff ); -} - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_internal.h */ diff --git a/components/security/mbedtls/include/mbedtls/ssl_ticket.h b/components/security/mbedtls/include/mbedtls/ssl_ticket.h deleted file mode 100644 index 7c6bc61b..00000000 --- a/components/security/mbedtls/include/mbedtls/ssl_ticket.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * \file ssl_ticket.h - * - * \brief TLS server ticket callbacks implementation - * - * 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) - */ -#ifndef MBEDTLS_SSL_TICKET_H -#define MBEDTLS_SSL_TICKET_H - -/* - * This implementation of the session ticket callbacks includes key - * management, rotating the keys periodically in order to preserve forward - * secrecy, when MBEDTLS_HAVE_TIME is defined. - */ - -#include "ssl.h" -#include "cipher.h" - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Information for session ticket protection - */ -typedef struct -{ - unsigned char name[4]; /*!< random key identifier */ - uint32_t generation_time; /*!< key generation timestamp (seconds) */ - mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ -} -mbedtls_ssl_ticket_key; - -/** - * \brief Context for session ticket handling functions - */ -typedef struct -{ - mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ - unsigned char active; /*!< index of the currently active key */ - - uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ - - /** Callback for getting (pseudo-)random numbers */ - int (*f_rng)(void *, unsigned char *, size_t); - void *p_rng; /*!< context for the RNG function */ - -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} -mbedtls_ssl_ticket_context; - -/** - * \brief Initialize a ticket context. - * (Just make it ready for mbedtls_ssl_ticket_setup() - * or mbedtls_ssl_ticket_free().) - * - * \param ctx Context to be initialized - */ -void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); - -/** - * \brief Prepare context to be actually used - * - * \param ctx Context to be set up - * \param f_rng RNG callback function - * \param p_rng RNG callback context - * \param cipher AEAD cipher to use for ticket protection. - * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. - * \param lifetime Tickets lifetime in seconds - * Recommended value: 86400 (one day). - * - * \note It is highly recommended to select a cipher that is at - * least as strong as the the strongest ciphersuite - * supported. Usually that means a 256-bit key. - * - * \note The lifetime of the keys is twice the lifetime of tickets. - * It is recommended to pick a reasonnable lifetime so as not - * to negate the benefits of forward secrecy. - * - * \return 0 if successful, - * or a specific MBEDTLS_ERR_XXX error code - */ -int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - mbedtls_cipher_type_t cipher, - uint32_t lifetime ); - -/** - * \brief Implementation of the ticket write callback - * - * \note See \c mbedlts_ssl_ticket_write_t for description - */ -mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; - -/** - * \brief Implementation of the ticket parse callback - * - * \note See \c mbedlts_ssl_ticket_parse_t for description - */ -mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; - -/** - * \brief Free a context's content and zeroize it. - * - * \param ctx Context to be cleaned up - */ -void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_ticket.h */ diff --git a/components/security/mbedtls/include/mbedtls/threading.h b/components/security/mbedtls/include/mbedtls/threading.h deleted file mode 100644 index c665ddf3..00000000 --- a/components/security/mbedtls/include/mbedtls/threading.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * \file threading.h - * - * \brief Threading abstraction layer - * - * 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) - */ -#ifndef MBEDTLS_THREADING_H -#define MBEDTLS_THREADING_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ -#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ - -#if defined(MBEDTLS_THREADING_PTHREAD) -//#include -#include -typedef struct -{ - SemaphoreHandle_t mutex; - char is_valid; -} mbedtls_threading_mutex_t; -#endif - -#if defined(MBEDTLS_THREADING_ALT) -/* You should define the mbedtls_threading_mutex_t type in your header */ -#include "threading_alt.h" - -/** - * \brief Set your alternate threading implementation function - * pointers and initialize global mutexes. If used, this - * function must be called once in the main thread before any - * other mbed TLS function is called, and - * mbedtls_threading_free_alt() must be called once in the main - * thread after all other mbed TLS functions. - * - * \note mutex_init() and mutex_free() don't return a status code. - * If mutex_init() fails, it should leave its argument (the - * mutex) in a state such that mutex_lock() will fail when - * called with this argument. - * - * \param mutex_init the init function implementation - * \param mutex_free the free function implementation - * \param mutex_lock the lock function implementation - * \param mutex_unlock the unlock function implementation - */ -void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), - void (*mutex_free)( mbedtls_threading_mutex_t * ), - int (*mutex_lock)( mbedtls_threading_mutex_t * ), - int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); - -/** - * \brief Free global mutexes. - */ -void mbedtls_threading_free_alt( void ); -#endif /* MBEDTLS_THREADING_ALT */ - -#if defined(MBEDTLS_THREADING_C) -/* - * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock - * - * All these functions are expected to work or the result will be undefined. - */ -extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); -extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); -extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); -extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); - -/* - * Global mutexes - */ -extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; -extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; -#if defined(MBEDTLS_ECP_INTERNAL_ALT) -extern mbedtls_threading_mutex_t mbedtls_threading_ecp_mutex; -#endif -#endif /* MBEDTLS_THREADING_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* threading.h */ diff --git a/components/security/mbedtls/include/mbedtls/threading_alt.h b/components/security/mbedtls/include/mbedtls/threading_alt.h deleted file mode 100644 index d12d5bc5..00000000 --- a/components/security/mbedtls/include/mbedtls/threading_alt.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef MBEDTLS_THREADING_ALT_H -#define MBEDTLS_THREADING_ALT_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct -{ - aos_mutex_t mutex; - char is_valid; -} mbedtls_threading_mutex_t; - -void threading_mutex_init(mbedtls_threading_mutex_t *mutex); -void threading_mutex_free(mbedtls_threading_mutex_t *mutex); -int threading_mutex_lock(mbedtls_threading_mutex_t *mutex); -int threading_mutex_unlock(mbedtls_threading_mutex_t *mutex); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_THREADING_ALT_H */ diff --git a/components/security/mbedtls/include/mbedtls/timing.h b/components/security/mbedtls/include/mbedtls/timing.h deleted file mode 100644 index ae7a713e..00000000 --- a/components/security/mbedtls/include/mbedtls/timing.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * \file timing.h - * - * \brief Portable interface to the CPU cycle counter - * - * 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) - */ -#ifndef MBEDTLS_TIMING_H -#define MBEDTLS_TIMING_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if !defined(MBEDTLS_TIMING_ALT) -// Regular implementation -// - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief timer structure - */ -struct mbedtls_timing_hr_time -{ - unsigned char opaque[32]; -}; - -/** - * \brief Context for mbedtls_timing_set/get_delay() - */ -typedef struct -{ - struct mbedtls_timing_hr_time timer; - uint32_t int_ms; - uint32_t fin_ms; -} mbedtls_timing_delay_context; - -extern volatile int mbedtls_timing_alarmed; - -/** - * \brief Return the CPU cycle counter value - * - * \warning This is only a best effort! Do not rely on this! - * In particular, it is known to be unreliable on virtual - * machines. - */ -unsigned long mbedtls_timing_hardclock( void ); - -/** - * \brief Return the elapsed time in milliseconds - * - * \param val points to a timer structure - * \param reset if set to 1, the timer is restarted - */ -unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); - -/** - * \brief Setup an alarm clock - * - * \param seconds delay before the "mbedtls_timing_alarmed" flag is set - * - * \warning Only one alarm at a time is supported. In a threaded - * context, this means one for the whole process, not one per - * thread. - */ -void mbedtls_set_alarm( int seconds ); - -/** - * \brief Set a pair of delays to watch - * (See \c mbedtls_timing_get_delay().) - * - * \param data Pointer to timing data - * Must point to a valid \c mbedtls_timing_delay_context struct. - * \param int_ms First (intermediate) delay in milliseconds. - * \param fin_ms Second (final) delay in milliseconds. - * Pass 0 to cancel the current delay. - */ -void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); - -/** - * \brief Get the status of delays - * (Memory helper: number of delays passed.) - * - * \param data Pointer to timing data - * Must point to a valid \c mbedtls_timing_delay_context struct. - * - * \return -1 if cancelled (fin_ms = 0) - * 0 if none of the delays are passed, - * 1 if only the intermediate delay is passed, - * 2 if the final delay is passed. - */ -int mbedtls_timing_get_delay( void *data ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_TIMING_ALT */ -#include "timing_alt.h" -#endif /* MBEDTLS_TIMING_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_SELF_TEST) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_timing_self_test( int verbose ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* timing.h */ diff --git a/components/security/mbedtls/include/mbedtls/version.h b/components/security/mbedtls/include/mbedtls/version.h deleted file mode 100644 index 32703463..00000000 --- a/components/security/mbedtls/include/mbedtls/version.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file version.h - * - * \brief Run-time version information - * - * 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) - */ -/* - * This set of compile-time defines and run-time variables can be used to - * determine the version number of the mbed TLS library used. - */ -#ifndef MBEDTLS_VERSION_H -#define MBEDTLS_VERSION_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -/** - * The version number x.y.z is split into three parts. - * Major, Minor, Patchlevel - */ -#define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 4 -#define MBEDTLS_VERSION_PATCH 1 - -/** - * The single version number has the following structure: - * MMNNPP00 - * Major version | Minor version | Patch version - */ -#define MBEDTLS_VERSION_NUMBER 0x02040100 -#define MBEDTLS_VERSION_STRING "2.4.1" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.4.1" - -#if defined(MBEDTLS_VERSION_C) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Get the version number. - * - * \return The constructed version number in the format - * MMNNPP00 (Major, Minor, Patch). - */ -unsigned int mbedtls_version_get_number( void ); - -/** - * Get the version string ("x.y.z"). - * - * \param string The string that will receive the value. - * (Should be at least 9 bytes in size) - */ -void mbedtls_version_get_string( char *string ); - -/** - * Get the full version string ("mbed TLS x.y.z"). - * - * \param string The string that will receive the value. The mbed TLS version - * string will use 18 bytes AT MOST including a terminating - * null byte. - * (So the buffer should be at least 18 bytes to receive this - * version string). - */ -void mbedtls_version_get_string_full( char *string ); - -/** - * \brief Check if support for a feature was compiled into this - * mbed TLS binary. This allows you to see at runtime if the - * library was for instance compiled with or without - * Multi-threading support. - * - * \note only checks against defines in the sections "System - * support", "mbed TLS modules" and "mbed TLS feature - * support" in config.h - * - * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") - * - * \return 0 if the feature is present, - * -1 if the feature is not present and - * -2 if support for feature checking as a whole was not - * compiled in. - */ -int mbedtls_version_check_feature( const char *feature ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_VERSION_C */ - -#endif /* version.h */ diff --git a/components/security/mbedtls/include/mbedtls/x509.h b/components/security/mbedtls/include/mbedtls/x509.h deleted file mode 100644 index 27d5922e..00000000 --- a/components/security/mbedtls/include/mbedtls/x509.h +++ /dev/null @@ -1,335 +0,0 @@ -/** - * \file x509.h - * - * \brief X.509 generic defines and structures - * - * 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) - */ -#ifndef MBEDTLS_X509_H -#define MBEDTLS_X509_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "asn1.h" -#include "pk.h" - -#if defined(MBEDTLS_RSA_C) -#include "rsa.h" -#endif - -/** - * \addtogroup x509_module - * \{ - */ - -#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) -/** - * Maximum number of intermediate CAs in a verification chain. - * That is, maximum length of the chain, excluding the end-entity certificate - * and the trusted root certificate. - * - * Set this to a low value to prevent an adversary from making you waste - * resources verifying an overlong certificate chain. - */ -#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 -#endif - -/** - * \name X509 Error codes - * \{ - */ -#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ -#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ -#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ -#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ -#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ -#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ -#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ -#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ -#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ -#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ -#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ -#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ -#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ -#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ -/* \} name */ - -/** - * \name X509 Verify codes - * \{ - */ -/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ -#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ -#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ -#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ -#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ -#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ -#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ -#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ -#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ -#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ -#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ -#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ -#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ -#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ -#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ -#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ -#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ -#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ -#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ -#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ -#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ - -/* \} name */ -/* \} addtogroup x509_module */ - -/* - * X.509 v3 Key Usage Extension flags - * Reminder: update x509_info_key_usage() when adding new flags. - */ -#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ -#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ -#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ -#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ -#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ -#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ -#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ -#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ -#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ - -/* - * Netscape certificate types - * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) - */ - -#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ -#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ -#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ -#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ -#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ -#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ -#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ -#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ - -/* - * X.509 extension types - * - * Comments refer to the status for using certificates. Status can be - * different for writing certificates or reading CRLs or CSRs. - */ -#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) -#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) -#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2) -#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3) -#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4) -#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ -#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6) -#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) -#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ -#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9) -#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10) -#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) -#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) -#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) -#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) - -#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) - -/* - * Storage format identifiers - * Recognized formats: PEM and DER - */ -#define MBEDTLS_X509_FORMAT_DER 1 -#define MBEDTLS_X509_FORMAT_PEM 2 - -#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \addtogroup x509_module - * \{ */ - -/** - * \name Structures for parsing X.509 certificates, CRLs and CSRs - * \{ - */ - -/** - * Type-length-value structure that allows for ASN1 using DER. - */ -typedef mbedtls_asn1_buf mbedtls_x509_buf; - -/** - * Container for ASN1 bit strings. - */ -typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; - -/** - * Container for ASN1 named information objects. - * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). - */ -typedef mbedtls_asn1_named_data mbedtls_x509_name; - -/** - * Container for a sequence of ASN.1 items - */ -typedef mbedtls_asn1_sequence mbedtls_x509_sequence; - -/** Container for date and time (precision in seconds). */ -typedef struct mbedtls_x509_time -{ - int year, mon, day; /**< Date. */ - int hour, min, sec; /**< Time. */ -} -mbedtls_x509_time; - -#if !defined(MBEDTLS_IOT_SPECIFIC) -/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ -/** \} addtogroup x509_module */ - -/** - * \brief Store the certificate DN in printable form into buf; - * no more than size characters will be written. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param dn The X509 name to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); -#endif - -/** - * \brief Store the certificate serial in printable form into buf; - * no more than size characters will be written. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param serial The X509 serial to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); - -/** - * \brief Check a given mbedtls_x509_time against the system time - * and tell if it's in the past. - * - * \note Intended usage is "if( is_past( valid_to ) ) ERROR". - * Hence the return value of 1 if on internal errors. - * - * \param time mbedtls_x509_time to check - * - * \return 1 if the given time is in the past or an error occured, - * 0 otherwise. - */ -int mbedtls_x509_time_is_past( const mbedtls_x509_time *time ); - -/** - * \brief Check a given mbedtls_x509_time against the system time - * and tell if it's in the future. - * - * \note Intended usage is "if( is_future( valid_from ) ) ERROR". - * Hence the return value of 1 if on internal errors. - * - * \param time mbedtls_x509_time to check - * - * \return 1 if the given time is in the future or an error occured, - * 0 otherwise. - */ -int mbedtls_x509_time_is_future( const mbedtls_x509_time *time ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_x509_self_test( int verbose ); - -/* - * Internal module functions. You probably do not want to use these unless you - * know you do. - */ -int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, - mbedtls_x509_name *cur ); -int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg ); -int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) -int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, - mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, - int *salt_len ); -#endif -int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); -int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, - void **sig_opts ); -int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, - mbedtls_x509_time *time ); -int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *serial ); -int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *ext, int tag ); -#if !defined(MBEDTLS_IOT_SPECIFIC) -int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, - mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const void *sig_opts ); -#endif -int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); -int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); -int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, - int critical, const unsigned char *val, - size_t val_len ); -int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ); -int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ); -int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - unsigned char *sig, size_t size ); - -#define MBEDTLS_X509_SAFE_SNPRINTF \ - do { \ - if( ret < 0 || (size_t) ret >= n ) \ - return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ - \ - n -= (size_t) ret; \ - p += (size_t) ret; \ - } while( 0 ) - -#ifdef __cplusplus -} -#endif - -#endif /* x509.h */ diff --git a/components/security/mbedtls/include/mbedtls/x509_crl.h b/components/security/mbedtls/include/mbedtls/x509_crl.h deleted file mode 100644 index 79884399..00000000 --- a/components/security/mbedtls/include/mbedtls/x509_crl.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * \file x509_crl.h - * - * \brief X.509 certificate revocation list parsing - * - * 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) - */ -#ifndef MBEDTLS_X509_CRL_H -#define MBEDTLS_X509_CRL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "x509.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \addtogroup x509_module - * \{ */ - -/** - * \name Structures and functions for parsing CRLs - * \{ - */ - -/** - * Certificate revocation list entry. - * Contains the CA-specific serial numbers and revocation dates. - */ -typedef struct mbedtls_x509_crl_entry -{ - mbedtls_x509_buf raw; - - mbedtls_x509_buf serial; - - mbedtls_x509_time revocation_date; - - mbedtls_x509_buf entry_ext; - - struct mbedtls_x509_crl_entry *next; -} -mbedtls_x509_crl_entry; - -/** - * Certificate revocation list structure. - * Every CRL may have multiple entries. - */ -typedef struct mbedtls_x509_crl -{ - mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ - mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ - - int version; /**< CRL version (1=v1, 2=v2) */ - mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ - - mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ - - mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ - - mbedtls_x509_time this_update; - mbedtls_x509_time next_update; - - mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ - - mbedtls_x509_buf crl_ext; - - mbedtls_x509_buf sig_oid2; - mbedtls_x509_buf sig; - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ - - struct mbedtls_x509_crl *next; -} -mbedtls_x509_crl; - -/** - * \brief Parse a DER-encoded CRL and append it to the chained list - * - * \param chain points to the start of the chain - * \param buf buffer holding the CRL data in DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, - const unsigned char *buf, size_t buflen ); -/** - * \brief Parse one or more CRLs and append them to the chained list - * - * \note Mutliple CRLs are accepted only if using PEM format - * - * \param chain points to the start of the chain - * \param buf buffer holding the CRL data in PEM or DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Load one or more CRLs and append them to the chained list - * - * \note Mutliple CRLs are accepted only if using PEM format - * - * \param chain points to the start of the chain - * \param path filename to read the CRLs from (in PEM or DER encoding) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Returns an informational string about the CRL. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param crl The X509 CRL to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crl *crl ); - -/** - * \brief Initialize a CRL (chain) - * - * \param crl CRL chain to initialize - */ -void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); - -/** - * \brief Unallocate all CRL data - * - * \param crl CRL chain to free - */ -void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); - -/* \} name */ -/* \} addtogroup x509_module */ - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_x509_crl.h */ diff --git a/components/security/mbedtls/include/mbedtls/x509_crt.h b/components/security/mbedtls/include/mbedtls/x509_crt.h deleted file mode 100644 index c694b758..00000000 --- a/components/security/mbedtls/include/mbedtls/x509_crt.h +++ /dev/null @@ -1,656 +0,0 @@ -/** - * \file x509_crt.h - * - * \brief X.509 certificate parsing and writing - * - * 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) - */ -#ifndef MBEDTLS_X509_CRT_H -#define MBEDTLS_X509_CRT_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "x509.h" -#include "x509_crl.h" - -/** - * \addtogroup x509_module - * \{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name Structures and functions for parsing and writing X.509 certificates - * \{ - */ - -/** - * Container for an X.509 certificate. The certificate may be chained. - */ -typedef struct mbedtls_x509_crt -{ - mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ - mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ - - int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ - mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ - mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ - - mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ - mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ - - mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ - mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ - - mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ - mbedtls_x509_time valid_to; /**< End time of certificate validity. */ - - mbedtls_pk_context pk; /**< Container for the public key context. */ - - mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ - mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ - mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ - mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ - - int ext_types; /**< Bit string containing detected and parsed extensions */ - int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ - int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ - - unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ - - mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ - - unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ - - mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ - - struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ -} -mbedtls_x509_crt; - -/** - * Build flag from an algorithm/curve identifier (pk, md, ecp) - * Since 0 is always XXX_NONE, ignore it. - */ -#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) - -/** - * Security profile for certificate verification. - * - * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). - */ -typedef struct -{ - uint32_t allowed_mds; /**< MDs for signatures */ - uint32_t allowed_pks; /**< PK algs for signatures */ - uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ - uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ -} -mbedtls_x509_crt_profile; - -#define MBEDTLS_X509_CRT_VERSION_1 0 -#define MBEDTLS_X509_CRT_VERSION_2 1 -#define MBEDTLS_X509_CRT_VERSION_3 2 - -#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 -#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 - -#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) -#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 -#endif - -#if defined(MBEDTLS_X509_CRT_WRITE_C) -/** - * Container for writing a certificate (CRT) - */ -typedef struct mbedtls_x509write_cert -{ - int version; - mbedtls_mpi serial; - mbedtls_pk_context *subject_key; - mbedtls_pk_context *issuer_key; - mbedtls_asn1_named_data *subject; - mbedtls_asn1_named_data *issuer; - mbedtls_md_type_t md_alg; - char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; - char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; - mbedtls_asn1_named_data *extensions; -} -mbedtls_x509write_cert; -#endif /* MBEDTLS_X509_CRT_WRITE_C */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * Default security profile. Should provide a good balance between security - * and compatibility with current deployments. - */ -extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; - -/** - * Expected next default profile. Recommended for new deployments. - * Currently targets a 128-bit security level, except for RSA-2048. - */ -extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; - -/** - * NSA Suite B profile. - */ -extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; - -/** - * \brief Parse a single DER formatted certificate and add it - * to the chained list. - * - * \param chain points to the start of the chain - * \param buf buffer holding the certificate DER data - * \param buflen size of the buffer - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, - size_t buflen ); - -/** - * \brief Parse one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. - * - * \param chain points to the start of the chain - * \param buf buffer holding the certificate data in PEM or DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code - */ -int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Load one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. - * - * \param chain points to the start of the chain - * \param path filename to read the certificates from - * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code - */ -int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); - -/** - * \brief Load one or more certificate files from a path and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. - * - * \param chain points to the start of the chain - * \param path directory / folder to read the certificate files from - * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code - */ -int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Returns an informational string about the - * certificate. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param crt The X509 certificate to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crt *crt ); - -/** - * \brief Returns an informational string about the - * verification status of a certificate. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param flags Verification flags created by mbedtls_x509_crt_verify() - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, - uint32_t flags ); - -/** - * \brief Verify the certificate signature - * - * The verify callback is a user-supplied callback that - * can clear / modify / add flags for a certificate. If set, - * the verification callback is called for each - * certificate in the chain (from the trust-ca down to the - * presented crt). The parameters for the callback are: - * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, - * int *flags). With the flags representing current flags for - * that specific certificate and the certificate depth from - * the bottom (Peer cert depth = 0). - * - * All flags left after returning from the callback - * are also returned to the application. The function should - * return 0 for anything but a fatal error. - * - * \note In case verification failed, the results can be displayed - * using \c mbedtls_x509_crt_verify_info() - * - * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the - * default security profile. - * - * \note It is your responsibility to provide up-to-date CRLs for - * all trusted CAs. If no CRL is provided for the CA that was - * used to sign the certificate, CRL verification is skipped - * silently, that is *without* setting any flag. - * - * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs - * \param ca_crl the list of CRLs for trusted CAs (see note above) - * \param cn expected Common Name (can be set to - * NULL if the CN must not be verified) - * \param flags result of the verification - * \param f_vrfy verification function - * \param p_vrfy verification parameter - * - * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED - * in which case *flags will have one or more - * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags - * set, - * or another error in case of a fatal error encountered - * during the verification process. - */ -int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); - -/** - * \brief Verify the certificate signature according to profile - * - * \note Same as \c mbedtls_x509_crt_verify(), but with explicit - * security profile. - * - * \note The restrictions on keys (RSA minimum size, allowed curves - * for ECDSA) apply to all certificates: trusted root, - * intermediate CAs if any, and end entity certificate. - * - * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs - * \param ca_crl the list of CRLs for trusted CAs - * \param profile security profile for verification - * \param cn expected Common Name (can be set to - * NULL if the CN must not be verified) - * \param flags result of the verification - * \param f_vrfy verification function - * \param p_vrfy verification parameter - * - * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED - * in which case *flags will have one or more - * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags - * set, - * or another error in case of a fatal error encountered - * during the verification process. - */ -int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) -/** - * \brief Check usage of certificate against keyUsage extension. - * - * \param crt Leaf certificate used. - * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT - * before using the certificate to perform an RSA key - * exchange). - * - * \note Except for decipherOnly and encipherOnly, a bit set in the - * usage argument means this bit MUST be set in the - * certificate. For decipherOnly and encipherOnly, it means - * that bit MAY be set. - * - * \return 0 is these uses of the certificate are allowed, - * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension - * is present but does not match the usage argument. - * - * \note You should only call this function on leaf certificates, on - * (intermediate) CAs the keyUsage extension is automatically - * checked by \c mbedtls_x509_crt_verify(). - */ -int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, - unsigned int usage ); -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ - -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) -/** - * \brief Check usage of certificate against extentedJeyUsage. - * - * \param crt Leaf certificate used. - * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or MBEDTLS_OID_CLIENT_AUTH). - * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). - * - * \return 0 if this use of the certificate is allowed, - * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. - * - * \note Usually only makes sense on leaf certificates. - */ -int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, - const char *usage_oid, - size_t usage_len ); -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) */ - -#if defined(MBEDTLS_X509_CRL_PARSE_C) -/** - * \brief Verify the certificate revocation status - * - * \param crt a certificate to be verified - * \param crl the CRL to verify against - * - * \return 1 if the certificate is revoked, 0 otherwise - * - */ -int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); -#endif /* MBEDTLS_X509_CRL_PARSE_C */ - -/** - * \brief Initialize a certificate (chain) - * - * \param crt Certificate chain to initialize - */ -void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); - -/** - * \brief Unallocate all certificate data - * - * \param crt Certificate chain to free - */ -void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/* \} name */ -/* \} addtogroup x509_module */ - -#if defined(MBEDTLS_X509_CRT_WRITE_C) -/** - * \brief Initialize a CRT writing context - * - * \param ctx CRT context to initialize - */ -void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); - -/** - * \brief Set the verion for a Certificate - * Default: MBEDTLS_X509_CRT_VERSION_3 - * - * \param ctx CRT context to use - * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or - * MBEDTLS_X509_CRT_VERSION_3) - */ -void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); - -/** - * \brief Set the serial number for a Certificate. - * - * \param ctx CRT context to use - * \param serial serial number to set - * - * \return 0 if successful - */ -int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); - -/** - * \brief Set the validity period for a Certificate - * Timestamps should be in string format for UTC timezone - * i.e. "YYYYMMDDhhmmss" - * e.g. "20131231235959" for December 31st 2013 - * at 23:59:59 - * - * \param ctx CRT context to use - * \param not_before not_before timestamp - * \param not_after not_after timestamp - * - * \return 0 if timestamp was parsed successfully, or - * a specific error code - */ -int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, - const char *not_after ); - -/** - * \brief Set the issuer name for a Certificate - * Issuer names should contain a comma-separated list - * of OID types and values: - * e.g. "C=UK,O=ARM,CN=mbed TLS CA" - * - * \param ctx CRT context to use - * \param issuer_name issuer name to set - * - * \return 0 if issuer name was parsed successfully, or - * a specific error code - */ -int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, - const char *issuer_name ); - -/** - * \brief Set the subject name for a Certificate - * Subject names should contain a comma-separated list - * of OID types and values: - * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" - * - * \param ctx CRT context to use - * \param subject_name subject name to set - * - * \return 0 if subject name was parsed successfully, or - * a specific error code - */ -int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, - const char *subject_name ); - -/** - * \brief Set the subject public key for the certificate - * - * \param ctx CRT context to use - * \param key public key to include - */ -void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); - -/** - * \brief Set the issuer key used for signing the certificate - * - * \param ctx CRT context to use - * \param key private key to sign with - */ -void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); - -/** - * \brief Set the MD algorithm to use for the signature - * (e.g. MBEDTLS_MD_SHA1) - * - * \param ctx CRT context to use - * \param md_alg MD algorithm to use - */ -void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); - -/** - * \brief Generic function to add to or replace an extension in the - * CRT - * - * \param ctx CRT context to use - * \param oid OID of the extension - * \param oid_len length of the OID - * \param critical if the extension is critical (per the RFC's definition) - * \param val value of the extension OCTET STRING - * \param val_len length of the value data - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, - const char *oid, size_t oid_len, - int critical, - const unsigned char *val, size_t val_len ); - -/** - * \brief Set the basicConstraints extension for a CRT - * - * \param ctx CRT context to use - * \param is_ca is this a CA certificate - * \param max_pathlen maximum length of certificate chains below this - * certificate (only for CA certificates, -1 is - * inlimited) - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, - int is_ca, int max_pathlen ); - -#if defined(MBEDTLS_SHA1_C) -/** - * \brief Set the subjectKeyIdentifier extension for a CRT - * Requires that mbedtls_x509write_crt_set_subject_key() has been - * called before - * - * \param ctx CRT context to use - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); - -/** - * \brief Set the authorityKeyIdentifier extension for a CRT - * Requires that mbedtls_x509write_crt_set_issuer_key() has been - * called before - * - * \param ctx CRT context to use - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); -#endif /* MBEDTLS_SHA1_C */ - -/** - * \brief Set the Key Usage Extension flags - * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) - * - * \param ctx CRT context to use - * \param key_usage key usage flags to set - * - * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, - unsigned int key_usage ); - -/** - * \brief Set the Netscape Cert Type flags - * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) - * - * \param ctx CRT context to use - * \param ns_cert_type Netscape Cert Type flags to set - * - * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, - unsigned char ns_cert_type ); - -/** - * \brief Free the contents of a CRT write context - * - * \param ctx CRT context to free - */ -void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); - -/** - * \brief Write a built up certificate to a X509 DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx certificate to write away - * \param buf buffer to write to - * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) - * \param p_rng RNG parameter - * - * \return length of data written if successful, or a specific - * error code - * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. - */ -int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a built up certificate to a X509 PEM string - * - * \param ctx certificate to write away - * \param buf buffer to write to - * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) - * \param p_rng RNG parameter - * - * \return 0 if successful, or a specific error code - * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. - */ -int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_X509_CRT_WRITE_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_x509_crt.h */ diff --git a/components/security/mbedtls/include/mbedtls/x509_csr.h b/components/security/mbedtls/include/mbedtls/x509_csr.h deleted file mode 100644 index fe9843cb..00000000 --- a/components/security/mbedtls/include/mbedtls/x509_csr.h +++ /dev/null @@ -1,298 +0,0 @@ -/** - * \file x509_csr.h - * - * \brief X.509 certificate signing request parsing and writing - * - * 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) - */ -#ifndef MBEDTLS_X509_CSR_H -#define MBEDTLS_X509_CSR_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "x509.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \addtogroup x509_module - * \{ */ - -/** - * \name Structures and functions for X.509 Certificate Signing Requests (CSR) - * \{ - */ - -/** - * Certificate Signing Request (CSR) structure. - */ -typedef struct mbedtls_x509_csr -{ - mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ - mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ - - int version; /**< CSR version (1=v1). */ - - mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ - mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ - - mbedtls_pk_context pk; /**< Container for the public key context. */ - - mbedtls_x509_buf sig_oid; - mbedtls_x509_buf sig; - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ -} -mbedtls_x509_csr; - -/** - * Container for writing a CSR - */ -typedef struct mbedtls_x509write_csr -{ - mbedtls_pk_context *key; - mbedtls_asn1_named_data *subject; - mbedtls_md_type_t md_alg; - mbedtls_asn1_named_data *extensions; -} -mbedtls_x509write_csr; - -#if defined(MBEDTLS_X509_CSR_PARSE_C) -/** - * \brief Load a Certificate Signing Request (CSR) in DER format - * - * \note CSR attributes (if any) are currently silently ignored. - * - * \param csr CSR context to fill - * \param buf buffer holding the CRL data - * \param buflen size of the buffer - * - * \return 0 if successful, or a specific X509 error code - */ -int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, - const unsigned char *buf, size_t buflen ); - -/** - * \brief Load a Certificate Signing Request (CSR), DER or PEM format - * - * \note See notes for \c mbedtls_x509_csr_parse_der() - * - * \param csr CSR context to fill - * \param buf buffer holding the CRL data - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Load a Certificate Signing Request (CSR) - * - * \note See notes for \c mbedtls_x509_csr_parse() - * - * \param csr CSR context to fill - * \param path filename to read the CSR from - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Returns an informational string about the - * CSR. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param csr The X509 CSR to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_csr *csr ); - -/** - * \brief Initialize a CSR - * - * \param csr CSR to initialize - */ -void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); - -/** - * \brief Unallocate all CSR data - * - * \param csr CSR to free - */ -void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); -#endif /* MBEDTLS_X509_CSR_PARSE_C */ - -/* \} name */ -/* \} addtogroup x509_module */ - -#if defined(MBEDTLS_X509_CSR_WRITE_C) -/** - * \brief Initialize a CSR context - * - * \param ctx CSR context to initialize - */ -void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); - -/** - * \brief Set the subject name for a CSR - * Subject names should contain a comma-separated list - * of OID types and values: - * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" - * - * \param ctx CSR context to use - * \param subject_name subject name to set - * - * \return 0 if subject name was parsed successfully, or - * a specific error code - */ -int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, - const char *subject_name ); - -/** - * \brief Set the key for a CSR (public key will be included, - * private key used to sign the CSR when writing it) - * - * \param ctx CSR context to use - * \param key Asymetric key to include - */ -void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); - -/** - * \brief Set the MD algorithm to use for the signature - * (e.g. MBEDTLS_MD_SHA1) - * - * \param ctx CSR context to use - * \param md_alg MD algorithm to use - */ -void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); - -/** - * \brief Set the Key Usage Extension flags - * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) - * - * \param ctx CSR context to use - * \param key_usage key usage flags to set - * - * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); - -/** - * \brief Set the Netscape Cert Type flags - * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) - * - * \param ctx CSR context to use - * \param ns_cert_type Netscape Cert Type flags to set - * - * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, - unsigned char ns_cert_type ); - -/** - * \brief Generic function to add to or replace an extension in the - * CSR - * - * \param ctx CSR context to use - * \param oid OID of the extension - * \param oid_len length of the OID - * \param val value of the extension OCTET STRING - * \param val_len length of the value data - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, - const char *oid, size_t oid_len, - const unsigned char *val, size_t val_len ); - -/** - * \brief Free the contents of a CSR context - * - * \param ctx CSR context to free - */ -void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); - -/** - * \brief Write a CSR (Certificate Signing Request) to a - * DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx CSR to write away - * \param buf buffer to write to - * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) - * \param p_rng RNG parameter - * - * \return length of data written if successful, or a specific - * error code - * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. - */ -int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a CSR (Certificate Signing Request) to a - * PEM string - * - * \param ctx CSR to write away - * \param buf buffer to write to - * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) - * \param p_rng RNG parameter - * - * \return 0 if successful, or a specific error code - * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. - */ -int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_X509_CSR_WRITE_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_x509_csr.h */ diff --git a/components/security/mbedtls/lib/ARM968E-S/libmbedtls.a.dbg b/components/security/mbedtls/lib/ARM968E-S/libmbedtls.a.dbg deleted file mode 100644 index ad0aeb55724871c0ac399ddd3f54a1491a733fbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580266 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

wxE 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 IWsLFu0PaLT^8f$< diff --git a/components/security/mbedtls/lib/Cortex-M4/IAR/libmbedtls.a.dbg b/components/security/mbedtls/lib/Cortex-M4/IAR/libmbedtls.a.dbg deleted file mode 100755 index cd3e5238013aadf9f26b804c2f3d12d55a983036..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 415804 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 diff --git a/components/security/mbedtls/lib/Cortex-M4/KEIL/libmbedtls.lib.dbg b/components/security/mbedtls/lib/Cortex-M4/KEIL/libmbedtls.lib.dbg deleted file mode 100755 index 84ae86170496a2c08b2b00a9ed20fb261bd6578c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 319236 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 -uDO#i?%3&+GqiX(kOPZH zj0SSMk?2uF@SFZ-jPc-83?7cX*XXQUzmwl?!!Fmj|*wIk!Sn{*DaYNSa>9Z1eWy-i5XNRf2L zj-#gnxN|V(IW4@7^cIqH&}F-k_8|2-L_m%`+QGgmL~;)5X56vwoPJ{26KD&!`Fs}o zXQcg5%;%5J@gf>{z?8pyg7SJWHX^km9Y%7Fc|cx;Za#L~jO09MbIMr-+sv+_ubhK@ z%cnv2AuWusgMCIipT0Cj(60hNeegBXF(l{sA&_^F*yjyM&e00_a>(;~%ekoFB?LG0 zyykNbey@)-UWQJfq2@?J-l6kTiq65lxEbjdr2P)jKxe#EnYxO!&I< zZG|SwZ_$YU-+5Czgky<^6Dn4r{ zMwd_hD<#=dIG`3utzCNFx;0(hn@U%7Enc~J>5}dhYfIOzInOF7JyA*5s`FN?Te7s& za9X9E7p`1dx?$0(u4}~-WLK{4TCsFZ>7q3&N3XhY z)zZ;R7cK4@J$6CG=<-n6xQoUJ2#qfvSK8FIYTd?h6<*F#x5h>1b#|><`hTQGG`)2B zdFMsdJhr5wq|B-R|46+apExy@uHCfu|G(PsH;LD-Sb$D1IgjDMOxLRJrE69#T2a!; z_4B;0)tyV%XnetvrOOtrThYCsd(-NrYe7Rmt?ga{DsW863y^^{GMIZ;E-^ygT`QNa z7j>YnzCcr1kygESU01g#LuHHBt}4^z8^?ymhp`3ctuf}1jvVU%|LPTsx|dzJX5|9b z;VL#r=c4kl<21fx>Edx*Ir_jkVotx>k`cOGrN`#KlvU%C&qkDmI9-T@qV^ zeFX-KDg2G42IT}x^RJkCdaf@nqTr)Js-QktkhlA)oZQm<<#Wyv9gVRQH`+-hzW4~v zPll@sdvh>&Ms8khkKMoHnevdmxnz3i`$uY|?+fd=g-Dj(6yRpO` z7qlCzLtVAIuUK(up}n!Bux3uv#H>8jHm3<_S=QX*i8-Zb7gvO)HrcaE#@J;+PYd6* z@mK$#Ei9MpE%bvH) zF6`KF{_W@QzM!e={I0$+c3wwMuBR718K_DMwugGkTSr1;?UyyBd$aSlm$421wK7;| zKRvLd)V_D+3HFufJ_dh0hmZ-rgaq?5zB3dv4Gk75@;r)*jV3t#<0XD`(VB z^(93x{ySfx6KdvP>FXas{ceF8>gyLl=sV3sqZ4`GDvBZ;9tA?=IQmsI;pu3???K4* znEh5X%ZJCYe0m(^pT|+IC|2pYS-E*0-PaYvz(^n6Sgdk$bMtd^Jk-Nr1KC460$Q23 zA6|*p_U~d9w3n9H!%FO>!P3HEc{#cHd3HkZw5ELa)3BhY8@G>+Zu)~IQRY2eqJsHl zb;E||ug`A^*(-x~a>+H%E?p(?Lsca*7gu{ju9KDB6+Js{}u!-HiiUpFbXY*SU#L8ck#3q;d!KD*a+HKT3R+PjE)$Vn>(_~ zKBweiyRh1x6SPNqSH3=_AaYLm^8C=1HTK48dq_#HC%%7J>~=|BPF_y)#3p-V5aHlq z>M2vs3LPt4HJ&-=&?tCY9LxF&n?1RFY?BEjz!){w3a!eiVIB9V{J< zHLsLIGJe40lU8RNci$kSjy_4ZJ z>8iRQJG6ljq$4@ErAbymEY4*$Im`2>PPG%NyOysj%bPl9UhbqhyK}D&GnY1vwqL)r zvGcL*eKXF>F?)g3TPoci7yU(5! zwEwWK5rg@%#1dalL08fOn{+|^_+ zYaEMC%PS3K=jHWa_k!6ow`*>3-uB!w`^{C28}iT1wZEUbv(rvLP&URMdbz!M#HPg~yk@v;Cmn)WjnaE|_2S`hft7X-&3b1h!$W$zL#y?rV!cKaKISGi_c}q)cn(TvHc80P;c?%}p zJ9qy2b$L^BHqWWq*Lg?t#H@49x4SWPOY;6O_nxwQ?Z0g4E}fB8RyMlSR~*RAUt3oj znzl4Ir`%4symWTK)TQ>PR!Pqp=%X*Kj=2ahds)!FX=_PMj-A@wdV20i46wZX{PFqO z*x2URH!gg=>7Fvg%dYaW9y_(9z_V3+ zFh}9*?7EAvri`x1h2xtJ+7}(L2L?Se_78GYx@SE8YpgrwspFcwF3u9H; zsEJM-VzwOcXL+CZna;~1HzuXuGN66u6I*3;Y-xMf$un=TQsKhJTr3t1rs7E6Czu^34Mn&7-0+X>`%6h*VIgCY3-`E z<$KdkwPtC&I&6YnBel%1p3|-6m0dbVUalgX2zB6B7j*Qsrn<;xD;H^vd(tJYI{!P z>pbh3?zgL&+koPJ`zo)4>`2D4<`epBlxyx^CU&Ub|IB_JM=aQ42hGOmw!5@x*?gqR z+d!Ey(c=WR{)eO^7sm$U14qRxOux>v+r)ogyu6>Td&XtGJeI@Voy+ zYr`^sm+n)4__C9hb?h8jS37T5o>`~2tJ z-fCI*5q-P&AEu>>-+R9A zVy9xRX+!IeSYX$(k>}PSLl0i`Fe86N>Cg+fJMME2pFW)4uZ=EhqNv zbhAILR!jfLFJ6%~t<$p3UF?#4Xse_959@cV-H=#veuv0UN$Cl#`NHQ;=J;L>f*fVg}F1U@+xa9T}8RY)wwlQdF9o*x8se-$j%x&d`#}J?9+3zCu9yD zIP#S2-0aM(!S26f2HI_$Jo^K(p_!MI7ggBIf>hmaDk`n5F3zo}t*NZ7;l5UGe$A}t z46;XNjy^qStXr;v!u+b)l{L9~4}GuznL~00XOGU!95^C-`0ybEb36Cyl6y+#2v@$k zu)4aWqCB^%&|0lqXkMP~lLd{?T*LJY%pQ|#cc`o>8D7Z@z5hIZVXd0l%4kaE^xXUk zyDvAZ#w#h$omo;|P%$&NrlOK&xO-^P!v1|VTZj^CW?pH2Zjt?3U0hfYU4oopxueGn z%pEvk0 zH9phsEEn38`4v?K(HdDit*6So0=r>2HMh)e8hd4V`F4XbKUyw2=fd)W$_lMgrQ}ss zTAXVgD>uK;HoL7EZR%*#*hpHroxAkR&CJO3igKsgytH^#(aLQy^+8+S(AISm+J?;> zlws4WZ`D{&RS(OZQevGrejC{)DN4AD=~;u+V}e5NzGH5s-DOPdNjU?vvWAR2C3n=w z?A(DPvvMb9j~+F~%d4#^_Sb}eA3oRbv~K^h^;j0IR_R)ObUII4BHVvsUC-^BZilnG zsM-^w^>8z_)SFRQRZ=uNx4L9%ZeHnBTVXS*ie^XG%!sVq5m{ZLQ~7hZZBUd~lUJG> z+k=bpN=j?13KOU6mKdHC3rA&T=Z+aWI(y&KCh>BY(vJ>+=@zD z`&DYDi%JT-SQE<&r&iRIXiM#DYpNTto4VbB*4j<)TpN097ffiH-)GggN{UMIEvE_=WbO+bTMz5!woF1gh@RrJHAegj7RTS&6^D zXjf-#CvJZ=&bA4k2gEj;`bK_nVg7X2mx}YMi#_XbZf~uv&YPMztOVURKQFh$ZpGIY z#%ny%p^ z)?d`FU>|jh>^|ghqo{2VI)x48wKfpi=Fz4}82-xgX4%+PQ>=`V8P?W0g|Trtx(F;{ zmJLN3hN_E8ifR~)^6k^C#Fe2%NOO$;+(fet24Wo~ z>~Iz|%*N$njj6Sj1?t5?vfsKOwb(}WSXOlFsr%>pTa4k_YIdV@uzu^Te~p>e%8Hrg z{=i(C7r)tTVN`>)f+Y^GrQm3oX^(qa7c9^QkM%1S!VP8CA#w!e%VX`)h~N%0+H2gWZ0=C2V~YBzWtHVs+s;+! z&I5`Is-pF4mmh5BC8KgjXP-JQd(7CN$0V!_YorbEc9K<5W&^kFox$R{abVP-jA&_& z=B^_o9Dw~H$Umm%s{7a~(NJ1hRTK=TRfT0X=G8eQ`R7J%c(6UocI@(Cf@t5gHo5^V zwtEH#0;|8G$UaF9#+>May8TxNV#Z*#&Gs@4u8FO4gQ-qjN(*g2tkA{@<{O)d8(-C= zV8w*{d2q&-(EYRwv3{0tE^KR@t`VJEMP*@CUX9KcW6e|zI;2l2sfdJ97B@_&>HFcJ>&|Kia?CIk_8^<40=ER%1OoRqWUo%)&pIozyw; zAneW`xc<^}7NvzXc8(v+GZ?r1%Ldz?1=Th2S2GD4PnT1=rn2*yV4ijIv)$$mSFfw2 z=rnB1jNzkB8#H9hV0S>6U1;NUP-&e4gEH(7VFYz*J-E{*cciYYh`XwbKa|as z%IJO(42*7YNvO|1`o(Qkozd4;hnFaJQODV0Xo+8Pgp%68oOxO&wx=lS<+>*^u5 zz@D&4sJA-LCbqK**UjzNR#Bye@Ph7aXQr`rt*UJYvu+<;v-uaDcIp)045@m%?U*m@_e^cd^mR8KPgJz}urM=K9k6ww{Q8KT*ro>jM#yz{nvQzWC z(r9u2Vs?yO&*qF7W9Mo4)-fvbi-T)ajbR$~!)M=iwiG=S+9BBQQRT6#e$Lo6xoyqz z@Tof&l(t{d!=lHve`tnIvg22yMlw4@=}1+R8#*6!S0%amcIH|bT$|-rR7@}N&qLg9 z;!d*tYg+4fi~|03sxHdyftwP$LesG@m?;B-yD{QU09;QEayc#Z$H(Y2ZdT!|++4dY zqh92OSgqRp8ape}LEp}>syKvn?`Eq;*AAgE+6{%S!`fmOyCY1n2rQr$%cgaw?a{L% zoxij9_-n##FPiP&6G&KScNkziwN7J;MIUgDuCARjtuWsP+`O65Ze(NZ=pi}TBeFVo z@8p%ZQ$3d-ES*+Gu-mw!P;|=hAxx(TI`9Qk(k|Q1ad&j0YgV^kw5z+z#9#;rCiQ1( zCxv+a1B`*wMv52kPu*RXsDW z(jVokT_1>E+1oJWt`eeky0cJq@L*Gx71TMe^g~q|nJmw0gS=(D|@ihJ@S7 zdVDmvl8c{f=I|j_cj6tWp!sTujt=fXR5?AmW^J`thtZAhxE>s=tJqP?I!^q#tlG%j z_LJuz9ia+x-6fIRC!!1J1|>Vf*4pZd z-EK^%Iy-Y{&cI>W(Mi#E$Y_TBzxZJC;vpLl;p<6i6%(XFeBT6OMyT)LL4U)XK@sdcY&G-g_t2`x$N zwBB~0_%kp@+9`Qe0k+|t{+X&T65!U_&n7mS_h7v z0u+_ZvVQG<+@z_ZBPW-+*6gy_HKf}Ww4>?r(ppvLqFNg-II7rq`F{+7?z-L|0{78$ zmuusjJ~Rs-&{;##On3;p6E0@k+l?KS?#`1wclD2dxpp>SEuB$epMdC2RpKpV zx5oVsJQL1vG;>|}Mr-je)PvJz-TaB}p`jsDP+i7NWb=$h8xTHF`w_R18rxP08H4UGaxpS3hCE*^X-l)MMxch5|$7vOI zv$?R$`k5|6>g)%u(RFUc1k3NAy6E$j;KD=wT!$Dt3slwWw$Yv0I!VGv6Fz|JLq^-% zYwZ|sjnlPPFrUQrblT{FIpcENHJBY>gEF)=dW%NwoMPjYKC!V+F@goOkJs#OolXg2 z9iJ;X?dS0q)A6@vlpdN>aOWg`^i@CMb2h(cvx`<&+C6t=2FI7WYa%$z$DQ-W?<4v= z*kaFa=V@D=GICscX6Mf7?z=qc`o>YGUY&cTx2Y;DwX>+g6VlHZIC?}!JDDo9Z?P1# zKdJo``|KgVINf@Fi8gY2mu{W9_3D0Rdi%2c%G$p6Ikugev@h#sab8t^abNoe&x{`J z%Pg!Zt}UAq*xpXS3aj*eC`&0Vsj>do-uBdzymE`f6$Mik**SGhd;4}&-|C8@n)LQl zrxsX+qpJOX_SKrcQ_E|uE$xf!;AEeGwAU?Yi;8N?^R{7=P^)7esKRBTd4;&oIZFi49LH?)O<4%C-Vcemp+4m>+cC?QF zFfaH#G-p`mm>!;uQt|yPVIa{d-9LXRE!z6HeQIR(X?6}gX3UULBXh?NvFneq`zkeP z$Vj`PnVl8gOXn0;Rk$6d*!o1ePPo-?V<*dQT-0#xZiFOU(Wzi?pDi|le?*DauR=O{ z+nuRkrTSxC+-Ec@V;_r`lm+EM39)NUr(sZP0lOm3g-TTjtV)S%+<_~*7( z=tif%yGC!HbDXtv0^P~1bT`O!;I<9pe|8z)U!qq@!EPP>z-X%Vo~n}k=#nr}+DGzy zq!gdyF4J`yVvFvMfgFU{*Mm7mkEkr;%o4jX8gyfB?AY)YG(PBC?imdCG{*4kkv8<# z#zy4Ww(!Rz9aQXJXxxq;2kjeb31__jFT05y%tDm_vQ-Of z!?LXrcR2KK{RWeTJ9coIsr}O3Bk`N#-$mCoSagQ_oHFqWUd@Z`zW(ED(e0dKPha2rNb)THz5;=Bkwv)K<9HK{f_lbJ!xek5)QE1!Op4SUj zQ^GEwEnZeJ!#+k(FW=`zjkVgI?X&Z2|C9AFGktYIYAdMCThf3h(2x zJ?L^;l?grFU6n*H!R-dtn;N-RK?NU|wn76nnlgSU=(3 z7kt7VGmtPT>gEYXkDXnvPTabtAmaIac#A`j`qh))~0Ue+Ig_MF&y_` zin|_Ez0tbjI*hxuqa&j_oEwPi_K4_xE}e?G`&)It_uWxz+s0n|Iq=8M(r80;=5|iUy)y5V%*@{DZFE{UwxXi6 zI^8~sNVikC^lVjcr*P>x{&N@=Rn;f_|32%}_kkPQzrFTjPwSqW+VCJ3D_uW&wL$Ru z0>yfTL`G`U`H=<5mnY?}%W!vDz44mtJ>~Ve_+jjY+kM+XWMv>Glos zjMUci4_MG(;rV9Yy(;4$$}fsUx+H6Y^tk#5Sp5T2 z8_(ZwLA`~Mi(S2Kk{72owznHZe|p<*8L17ldk;pNn{@%vbo zo3`mi^<%vyVfyg0gyZnCh1;#yo5ZgNwL3l@Y;n5%3w|cqFSg%Yo|KuAS})_pR4?Pe zGgED$p71J&=~0F)I0D8=%@)nc!!e{Su#VtEf@Ni%)Cp z%s6mNYNPn&9P7%)#B=ycCr^wH z<{28yEiZn%+3HHz*JrtD{V^!reh+^1+NZer4rjIr)B5{QgNrnNh363;tKI)stnCw@ zZ(S`RR(^bY_4==j)MoSdUr>MHeizqU6uHEWuLB|zl2cVS-TnnXdi7SFad=j0_u*g3!cg8dfOyEwAQYKv4Pr8d>J2!8Zxv5eGC;p1GSQ*vs0{5B8zm(`Ix)HpU2G1)L9XGiH6!5 zzwVY;99;%G(MS&}GAHk28#T0T6yFBDqANOm^87k&@b~S6Hgrn9FtIP_Rc;B}D0y>g zxc_Ro2dbfYdO?tvq%mi|9_>eX^;7mAaX@lfy~at0B^@4Vnsh|ckx9+#wX`bh{KTi# z^S;{~Um)Ve=Xzd5?~jT5iC9YfPsCnmb6|Xe#X2Ua7VV?S7RUcY?437><@a;1c~kkG zuKa#(J9dgr6!(5ION-c_tw@}HfBsaE|Ej!X%h&3e8=c`qlmaplz*gyYAe~L2p6S1iir$5lWl1tOivVX~ztLclQlO&do*z0E#Qx39Miu?1| z`De1_$Nxm^-PMWZ5B4smy!P2-%a8ww*!!^)%OB#cro6U9vilpfu_+?KH zVEgGUvaz3tjlzlL8+*GgTkY>=|B@|V?bkp5M?E<96Y-jarf=f?*RnNzy8S2F@-?mg z2!#I=|6)CD|E8hoo4WGrqutcc|1~aFeR?0a{}aF0tG**c^&RQzYZje<@IpI(>WGb8 ziS3Uc1yo=2P=0e)Usf=C*W06kl}`_qPmg8VZxOFWD8EH0zf~x|RVe@1Q2w!QdD=uv z9UJ{kzeK#_L*?dL` z1WnA3jU*}+@j8d{JI5w=`CUT!I%ACeM7*w{{I0P~`z>O7LE`+iSHylI-btbSlVX|n zTg2Y+oj85>P=1e4eveRouTXxkP=4=FzODpgKN0WbQ2xoWO#3ZjF9c0ozCNx$Y3%lY z`UJl?BlcH163h1s<@XQeYc!7iM7#l^`~hx$vAGP06}I0ZUPh>VMkqfsl%E;O&kE(o z_FNT=c-f)+?9lXsLivM2`KN^PPYLA@3FQxQ?Tz)KA))faLgk0K@;T8`!=k_Gmxwna zRDMJ#e`F|sq^mDB%8d+_&k2>!api|cOU0H%NfB>!sQlQ zH!W0tTC}8}UmD6Ub@f$7OO-}{^UIfq%9n@oD?|CQn*8ajLitsp>8nHe)oytjMN3sj zfAj0B4VAAAm9GtzpBXBzv&Yy^#Lhw!*Z-_oru}Ar$Rm_LJCr{slt0HU&!*`4l%KCx zD*HcvzW$0y5C^}>i2a?2#N|2H)%R<((7Dmy{PO3A%AfDb&yCK{&)2J%{U1O7)3`Xu zkr8ihsJ^+bzBSSEe!l+7rT^pS7f0JOH^^{Cym_Je=DGT=i<=d-wtv1W zUlT1gKl+6eIi zd8qv5uKe(5{g;QzFAbGn>dL^<*#++)1%9CZK(W;Q2784*Bn*UnwY|8udUmGgFE)?Gxith@=8$$8jq4=Iqe4ksM*zw@sq5N>XDU|P3&s6H@#s)|dMKV8iq8(ki$d|uq4@q# z96L7n%cp%`P0;6PX?FiW_gsS?t-rKL5c%cx7tn$q0P<)NWn%@BXPnz9d zxSLp4T4{Fw;AP_BE^hAqK-|g2>E7YdV-M@sV%4XSFU{@;WQ6iZk+09!(!5q)IdL}^ zAM4t!>GiounqA-D9-96U$~SQNCwQ-i^503wKhgV|IMtPJ@9D3NseV81;I&GKJ9^o~ z^){=2Gmf>t zm)D-yU*6u{X~h2YCwsNTeO!HgyeljYepKf*>|<;n80iT(CvdwIlZuD(Iu1;l>)PVsIa9_;dmc=r)ca`7;4 z7qLJ85#HCttzG^|?*MIhepKg)7HfU^)8}{tiMv=@nq9w53YD)Uzk|yk>s?CR(!~?J zHKFnkk-ypHPxN+&^1mQ|o6A4T`zw@xXxuGXEpG>lwY;5N`6=EYV!wR_-dV&qy8I$< z7V%CO7kifwYc^@#H18H-9n;h7?<+rIaqy%0y%mc8q`W@2O0&OZ)!0_FmPcjN?2oRs z(~9RuY5mCe=U3%TByMbZY4!*7W+ue7-qpm-T>eb&ZsK|_p5^UG$e-GGF)=MuMb@s-|kVtpo*=3V98XL0bO`ky9$iT$2t=XdWC>$sHWUF-cBD&N9x(QA41 znNOOx!W%@a>-{u4AIl@w=Q(M1zEu_EyZY^XDfaMC>)4}1(I;i&ABpo?7x<4{#eI`c zQ~%=^%c7Y))fxAlGiCAYy?d-p@jrZ{W1m?Gua8p+o@eS%QeBnTp_5xq_jIlQG+*#& zYVa))H^u*cja_0f_js_9g6BHjcO#VGKj0d?<|O#~bmo}T#%2!g(78(|FZi`{&*0Zy z-J*|5#Xp1^|Byak?@s)-2H!}sFRsL18W3NBp2rG3wiW(<_&&almiU69V0wGJG-2j0 zwpaAUzS9?1QV;O?Uq|3USbKj#+(W1~tv!nt_ho8J*w;5}gXGW`?t_XS%tirPYbg zRL6fQ(tjO9T+zgD5yuw|ZB8v*-KXFa8>dGXqYubOv-bHUqTkl|FE{yL`-x6vvrFj7 zn!r6(`p@6Ra^Imzc%MmhqB>vGil2|GHnu*)&qYQn`RA|y`=e#Fk3^@~=NARz-vp_W zT5I7K61hdvn{vKVV_}qk7Ow_F>{%iMja--ii2!8=H z*iO;6E!3Gb?z!OjJgtX)KKSZZM*JHV;-~U6?ICL026etL<}&?n!-l>a5MPCR%w8`- z+s9iMl*h4!k1V6^{G(Iy$RA){g)2IyReS zokh{^<&KSUU-;kmmzga!;pIH>3vS2hXr6lepcLT596ov zzx%YW-Pq6ZcbeE2Clb4=d!7B0e^(1_iEIxy;blT_~yqz@2jX(d9Z+mLg~ zpO3o6Re4>zr!-G;e@8p0C*_zV_h&^@(v$2{SIcja?-rySm*nYQP|ER1UR&8F$r~h3NV2<0 zzLR9zB=;xkQ%+2Be}g)uU6Os;X6fyd+@Fa}>A?E3^tGg~mzJ)3pDO<->EFwaN$yXo zYW>>ZU2^L=*q*JG-#N+d-kG+1!FqA^+Ispx>0Oe%ucb}zX?kntcE6blQTNU@eeYz`+BXz+Z$ay0wX}Nm{F>I=M%;v(ajUeIw@q4S-7ak<>t45}+ljmI z4b;7FMk~e@jSYDOWdI{EN4*6qI_o$oOdUj4pijJGE-FfU!HvMqQho^Vz zt&s7=bjxe|X}Xoy{;KvjxBlVE+4!XSXxwRxw#walSNl}1kz$*l8^7&?K(~KedF7`R zFm78sm~!FenPBN!FSaVZ6uY75>a+5yNA`7(p!O=gn& z^U^8PlDt()H?=$(pS2wF32EiFOFNG2l-BPWSbtah8q@FfT&~*V_Lp?OA87gPSGSyM zua@ghY0Ic#IoHy)y=^<#km=F~5KkaJOWJy! zCT+W|ljkRSyU0&Tw%9sH8)<`Rcg(`ESS0PZUM}tUeWkSN!pFTWmag^Sj(b`!#Np#! z7aezOd5Wa9=X`mgoo7jF%tNGqf?vy4_T3&^p(@`&T0BzPa*UNdlDrw@UoWj5J?Et5 z*^1k6JMO?;_y)d>d+;Ot5`*Je2ewCVX@lPsbo;lpPyJWRXS;xxa)G~pX}R81oZ@+3 zN^8%rrk3+h^lbYmu7}#M6*t6Se;Ca4Za!Ae8pU({^HJ6N5&2(B+gX!sdZk-cZvMTA zE2S;hdg6QKJnPS-e^0tQKeBq<`H|H#QvJZDbN#~Nxoq$GxCocv)u`uv)Ser06|TYc z7(TxW`j`0G8zv`yve8;!QBxc%#T z;^(B5dzZK^^B<0GKe74LD7Nh%v}c{gYHzqb!TDlByXyb%{bv{Ty^a5LzSvFsjg3E5 z(w1upuE(dbf%R+Ur%LNT&7>`VYiZ-hAZaUSlCesHH;40Mibn6o}eyX0H()P0)Y0Ftax{fm{KMT*rxoC^! zHNQA^e&miT7LT;_|Cf5&s2&@K-0{zrXM(0T=gCVsZd>g7ovmLRO5O4flD51P=~s5B za?4wcrKtT>?XW|M^IWt|=3;kzw)#70ezqP4N!818XnkntB|EkX&Z>+v{iY?zxS)9X7O`n5yNOG}`LrR~7lQCF7Za>ZE{MG7p{lM0rTVGcH z^_st}r&Tg;{CrWd<-cvJ{yq2+eu^4jmH#9Dip@;*bGMz-Sx>F(c%t-+g7X8mhKr)tMmi{&=ljyv%U+=CzC zr}!=Yh`-{W80?>J|5@r^f2AzseAkxO?dNt-*M6<#{-^P7zU6B<7opo9to&f68!xZq zeB9FCRcwRNC(@1w-%H!cQ|a$bqzzKG>bw-Y4$%0e`OlTMTx+DpKhi&vS6ja!zp?tA zl~1QXwnptYTF!RZ343A|4n`e^RemgLKU18r-mG12e6-~ns&?3X%Ten^@pepRc^jIp z9&C&n50%~;+h8Y5qn<9(=IiEX^DQF%33TH~Pus7E!{>XAs4tkWby+vxmXz-;ZQL9y zt$$9IHm+VL?L2dpwE4UF+5BH8u4nbAz0I+kwDRtFWczaw={2U>ISa$bo%y6M!K+dI zO839?qv>s!a5lh(XuF@6e5n6!fMi>#hbT4=!y}}1vKI1i|9*k;^=(4g9rf)u#p=g$ z6l%RF&ck9X!#TJJFGC%FG~F$DKfZu(;D`7-dTPH-S07#fu{e#`es%d;?<(i|kJ*;k z^&g9Ele+v29DzDd&~(~9vI-aDa$Jx1;%0mlx8ZZR6L;eW_!a(+^|fEwe4FD*crp&e zQ*Z>1K|NEf>2t9Vr=y-JR{l&p4==(?@CsaxH{dOJJ8r=H@IibGpTg(yW!#PL;D`7b zeuF>ZADCpvM=k&Ucn}_nN8mAdES`v+u?P0WOdNuva2!s;YMhN1-~zl9m*KUz5^qHv z_tlQa@fmypU&a66m#F*7n(kNJizzk$DE%;OiMpOwdT-SAhT_q97EVK5=PUnmyahMl zgZLD_jCwX&(|v~adIJ|X#2UO5m*KUz5^u#jP|rN8-hbo6_&7d;FQCp-RQ^5u0_)j8 zsPsedMC^&#I2v=Y6zAX_xC!-)vzs4&j;T7Yu=yQ{?Xf3j;z&Fl3-J>C7e0tD<2(2n z{)7$e0HFCEiajtBN8uSb6|3T`dNx^cZ`8BN zibtcKO;$V&XW(VH0&l~6P|qZ5x@Yk<`~bf}J)5j@P3#yfTVW^ci>G1%R^qw12$$n3 z+>S5eE_@UBpq@$A{J+HS@mKsC>)ErwDwl$dunFo}W#zZTHrN5X;mJ51m*PXHXOLCT z&zNi{4vG)PW_SX2M?HJ2a+9zGXW~V;6j$P%_yBIhmr>6gtKKj0SKQB@9aef89)s<$ z7wQ>gl^cVTu?*+n#dtN|g8#yYaXY?-AK*9mCmxXM&$kJ-!cN#1hvI2ifM?_Rcqv|o zx8c3`81BIT;3xP4>a{3ZAE|gG9*^B{AdbW{uo!D`9$tYr;vINDK8ZW=9sC@B!FqN9 zq2)USo8yVt6SHv~7Gf!%J#(umAuf|pQ2-etziKbhL594n90lV6@kIId}nYavZ!aMO1d=6j7 z5Aj?46B``v*WUt%VKLU=Wq3WV#e4B({2e1r{d(JDKOBnVaSATPYw=dR8z07J@Kt;d zzrb|6(9`Ldm$YMklOz3dM@dURmbk67{6W&L zQ^#XI>2su&zfjs(e}lC7ts?y{;*G?QNh|l3wEDip?@6zBl%IYWHj`F=D{1?7UupG^ zz|rKNNnAlZhxh{GEAVE#ll;4-)w>P%NL#M&@E6kcLRXb*BQ3udjwF2=-iD8p{|bIW z`XAWDo{>;}9i-LQ9|uWm?+9u8)KsV4w<3Ke@wvoHTw4Sd)`d)&n3Qu_;TX4(%Nx9J}PawpOtOw9caWKN}KPe#6J-KN*qb|^BYK;{!rqk z#I1$Ni5*=Iu1woeDl zl$JjR&mujaxSY6}_`?n#7`2xNc<}CyTl(7e@*;@wBz|{g?T?eOg!C#r z2j@$h?mFVt#P<_#A$|qFmbN^4CQ{Qi#ctBlM-fjaJ{RYaem(JBcpvF65%0lINKZb| zulG|=?lTAFHcoK1mwE16*SIUz;Z@skX?je0U@yq1DCbc}|e_+?~%41p1^0N z&3~uN@Vw8Z&F359z2w*LVCh+&cbK&D>C(y_OL_+BL*yXO%O}5>_!2qT^X`&EJ?~km z`O4v*_a5TK-7;Ua++CeKAYsc-|P|Jgmf-aeScGMAvVHzeycn;;wfJw`BByxX z^ThwbPw_Y0uZxwleGx~0cpdQu zY2_csH}Mx~%k{S`_q>B_j8uFSo`5~EzpS+99Ed03G@OldWtHb$LA(;z;{&qB^In#= z{JTm2K+f>IKS@tM$zofcgXAnb|C3g}9dUQ^2g*5~cLw=+q%X#Gc%MAa^Iniv&nu+A zL;L~pSHwR{E1zOxxym<^79Wp&rHywZaV+W8(w6&tIoFP((x$(O^gHA{&wG;e-NawX z1)gWGNpa;5lomH5Zb96ExGV7~m@930DsdL+ONnp6b<&paZn?GSb2yiMA4>*ba9jtXhzpC|ow;kJ^2xTw&*9(w46a>3xYOkv{{M;%)f2wE4e+dr1FATK&Jt8|^%zpI?6q zJWg7AU*ZhnNmz*GI188H9n$LGBv*Ofi_(_=Rnp%j{u+OfR&GB#SJQNjNiC*cr06N_-3wB@@B zSCD>>w03QlciDL$@hj5Wx101IN#83s*!MW>Tv^i{A+20<;uDBF5ceYPM?8dhw6uE8 z##(9HaRK?4~l@c$LTRm?L@dn&V`U}Lb<9qliej{yu$7lOyVGfpHEnbM1;cd84KH+)KNn1Z} z;(O$OiNBD(zg-ilTq9}IwI)7+xI6L5#KVb46Hmj1()#hWcq{2!@D0*G!=Fh{ImMrE zI<}V9-?~X#u3p5a5a&o+&I00TK z#ivRCfcOXejr4=;8d&XZh3zl{&yu!06RCv9 zDe-m0D~bOtt({Nd3#5NW{5$Fachz?Q9xH9S?wCn>E^#68Y+O$IT3k>1Q}{mV-{W4= zn~w75+Xl0w&37D5A$%5&uk_da7UlVbZo!KOBnVaSB%Bg?JgRz}s;%zJ;ISkJxauKfk7U0`|ac%#knI zeN1Wnu9|qJwElH5>6a1TLcCU5d+s5ANLoFQN}KLQ(qAQhoA_h=8h=4=j7?|r-%naS zO^A;o?jdda55{q%m*Yaxuf@kne@$Aw@8W;)OY(ms);%?q+h5xJn-VuC?nrzR@mV+v z7m&Y%cqQ>#yc;)>zf)R!-pBuv{vD=_^Oxf|Y2|ugU(!z}o`wrZzlHc-e2nzBh`&UA zF;wk58hc5b&rr-Ey_C3$_;TW#@ix-`g%99Ml5r>gJ38#=g zTiV0X^NDZ8$D}RyPJEs8uZe#mK4gMlt|hjSHs37baX5waImDOZHFB5T@08Y0?!^a4 z-%k7j@mu(dwB>7Xx^JqqdfF17i~~tOleipfNMAy{5^p2@KDpcOA4prSm+%dIA3u>+ z?ib?yCi>-5q@_2-&eE1Q1Ba4cL_8DEBYhd(LHa|uUE28Ys(jP)zLK_le-j^dhM#|& zeA_Kg4fIZ!pQ9{s>H$wp@L2D2|iwd0vII<+uPZ z!yE7}+$gP{hl#gIoBj>rcZfeH{)zZEY2)JoXZrI=l@=dP++12cy`{B#7@kUc8F4l7 z6~wD>E$L4Xzl!gZ{u3T>mOr0krOl^1W|DpeaVb_yYw!8;1H1nyZ9T2S4WvISt-d#L z59vSRA-R5jOYA7EzEg-NV6L?JO_Lwn-yxJXzpHTt`L{`1e-DtpMOyh?(w5_6{F3wr zll}A~@EB?3JK`|XC*c&*XW(L7Oa246jr6yPzrr7-wWE8U??Cyf-B*^@p6PfFUW!*s zE4PmL9()KNBYy|+%fugJ(iEHC+MkBUORH}nj>9tYYl)W;uf}zxZ^1W6{|tX7JvHB- z-!a%$eqrxcm)6d)csl7t#1%LTFT_RC*4sV!2tJ2zU{Zl!E)`G0fj9zB#~C;eFURX~ zE#8NZ;q&+%dWHUcN8nlVE4%+7t-W)Jml0n>d@J!i#7_}FN4%T(YvR4c^@{xZ)1__K z&e((WVVF<)G~&5coXAm!z*8VGqZy~;u z_)+2~iFXpei~q%M@i%Gf^`K(E-b1DB@9D%{u@4TFR{jj)0xZL7@~@EAu2r~!^k<1* zBK`s+C4TwF*izbZbi;wt+C3CUNn4H*JQuIP>+lx56F1`yY4yE^@8XB#e@pxuCQtLr zABbtv=6@V!NNevHoJ{(;#Fyb!q~Aq+Kk;+YmS-37r^H_qr%d*9;>7+&qcVD^!2!%^cRUgC;kJI%KiBqhMlF=*MoQnj>c)^pMwkK zkDj+e+ICxwx0Ak^_z~jg@jd)S+WZ<+_%@POUpwNym`VC+I2|t{f3dW2e7XF^^X`_m zJdfcE_!jPwR{jg(Z;ADy2Tfm3+J4tqT0KXSe!R5lx{%(3ID_~UY18LRYgY}h+krZD!*K+ zwE49q?nFGC_)N?v{T$*Yc$KvEc9Z0cA?#rPhF@bW@!j}5>2Ko)r2kEP@GRyhZGIhaFis}_Y@8*n9T&-neZN9lySI}5g0%N$ zy+ZsBzK@^cm-qwzf`4Q3Y=1rn;6d0Jo8mFp3fp1_JPCW@0L;Q+I10z(M9f2b;k|43 zG%UwjoQ)Ua0=x{D;R;-dx8WVQ5jWu$+=|cO^Y|+6#`o|;`~tthU+@pqGdJ3v_3=PF z7@Odc*b~HB?XVN}#(p>o$Dm!#xccoh*Lfi>z$Lg8SKvxqFB|ypx0MeNKa5Y{ z)3_6N;fMHN{2IT<-_V9WH=lY*zV3Y&Hor7tJ0)=W$I6DDXRo4gy7wYj+>O{?(dp9r z;~*T0r{XxAiqo+QXW;p0uh4MyE|-n$ybD+18oUed#>ep~+=1@B3Rcf<;=|9%B)Kk-}m0e*sC;df|%P|(#^58e9{jY+FmE7Ujcai; zZo%he8_#UWGSMUS;1i!}bQDdpvTOXU?k$3{O z$G$iaPsMRK2`6I(R^uEz9~a;ycon+$Mc8t!CB75gdm$|SG2)l-ReTfQ#gFkb{1)|o zE4BN8`o0I@VR!_lV{7b+J+MD!qI<7|)jOWJ5KFKUYw#Sr058WYaRsi#HMkD%#`{q3 zb@7QpEzkDNXip{VU9*-Tc3--o-sK526`47Py9E)dQ zE*9Z5JR58AT%3y+sV51E!re@jq4fREx6_$GikT+_SxEAlkd+^`51-Ife_&mOXuj4!TK7NW{;vcvd>!+|@Fb&=NPOM$W6Q77( zusaUGEF6#en~dszd02=QSdHi5g?N?hY{zlD30LDCxB(x-C-FIa5#Pc0QGd%(^+)VP zU%L0Cn5o1^V+-tr?!72h&b=4K>`(eg+0FAtTf;jdu5e46VJhUxDc|cpx5(N8r)e8rxuR?1w{fBuG_m z^CR)ExECX-{&E~93q0=#Ovl!EB6h@qn2p0R2i^N=tiCgd%h0{2#?ogIpNkja#kc}j z;u>6s58%W21U`+gp?j~5&F=$Z_kJ6Te|_gwK6d>!Ax_wiHw5`V_u@qk0EzQy)=JT}Ircnr3}w%7rCVjmnP zm)QP><8dP9VIj_xOFi!#oQDhXGF*n&;f=T!@5Be?m7ezqZo}>P626Kb<7fD*TyEbl z#faVOQoKK=Vj8x_HrNAC#-Y+~vW~=YcsfqT0-TN&I2+Hy`RLwHW%XW9d=uV=ci=|c zgpcAA_$(RZ3%<8#~_zv8NoA6!A!&*VlsUg3}UEAB=2zBMbCV)xEfJ{8lkHJ*qau{-w0Avgjj$$RbZF5y(1 zj_1iuo_8TG!X5ulOg{Kf=#X!9(yc zJRVQPZrBq~k&oJQiZ~j_W3k-od8Js5GjT4?$EA2R-hembJ?P#;XZ3C&-ipuRi})J4 z_taVWFNnXvy%;&tU(Pgi@2#`)M-#WeuGj`C*z8*GPNu?P0U z3><>)J$qKqB;v_96{n+n-=38_pLhXYf=lsgycKUp_Z~i*{yyS|@iBY`pT}2mH@=4- z;t%NF-)Hq6(9B;y2VrAuipO9pY>OT6By{inv-$=QXW{s ztMLxpfRCVi&!8>OcH$kl3*W#`18Ua6AfI;&Ip>J7Z7mgPC{=o{nc?DOTc4JO}6DLR^k3a2>A4`_R3|(c1MW zv3sAR#jhxS$@5;vchJ4p(bC;}9nCLE{{er&ztO$-(aJSG#;>m_9)qp0Eq1_@uon)% zEF6y$u>{Mo24~@1oR62{6?iS)fUD8HXVRAcY2xSbWqb`kLie6YEB_6#d*7tRzZ3tB z2c`S#;}C3$&9D_7k0)b)9E3yhR2+wA;S?;vGMs^P@KU@2ufgl_7Q78N;bwdWpT}45 zb$k~;z(@rvDg8-U_Z>jQ*j(l!pZ2~b7|Y5ns^SLk5}R~cnjW!>v1DK zh>ze7+=*}Dd-w@{jz8gV*s!I)J{sZScoZIoZLt^j#o?HPxtNdDI1?A*VqAeMaSg7+ z2k>Eh0-wg$@ISZ*Kf)j6F1zoGe`9hhKm7na2peNlJO*3gN!SYq<8T~#kqJfUW!-ZHMkDf<9+x5K8{b}4%~?!;3xPMeusbHUaa5RU;Y$qhUs`bo`_wr zJNCtan1k-Uq_$r2iKpTW`KCS3f*0ZfyjH$#&-dVJT#Fm<9^8yu@M(MwU&hz)ZQO(Z z#V_zLOgh$Ijt1BekCN|s-Z6L_w#CkP5}ty?a2%eFld%A&V+GE@Id}=dPS_taaWsy{GcgY<A>!zb}Md=Xzm_x@a4jxUJ6 z!JqMWJfMxgya!=3OvjGc6*F)Uj=)oK0#3qwoQgB#7dGDDg}4B(#T#%nuEmYG2_MGC z@MU}rKgQ4STl^90pWrV~3Lb$+V>|hk=XJs!crs?-ARK|G;sl(8<>=lgZ1rA9ya1Qr zQoI&#K=+4!b7krHp5nUJodysn1zGUy@%QAA4^<-#aM|ocn)5G3vn^tfH&h>yc1u> z*YF*DAHT<+@h?njM}NR3*b%$p$=DwU;ZQsk$Dw=Qv$cORaWR%+HO|EIaUL$i<#;>Z zh4~RObJ^Nugw#IhY347qln1O?E9G;GOScs)q zi8JvWoR5oe87{}0a5dhC58%`I9KMck;%DgIgKh2KOC0IwuZIKiU~G;pu^o28-q;Uw za4b&70-TN&I0NV4B3y!3;kCE{-TSp|`5z>H1b5(0d=EcF_rC2P?ejdv=3ki9$&cOp zw=KOPadT{mCt!Q*hCQ)AX5vsBiR18eEXGniNB-h@7vMr%jLUF2-i~+Szwtrbiresc zd@kH#1-O;@--0B%foQ=aV2XiqW zr(ro>hzroYPu%Lgk@$Xm2p`9%a2LLT|HUuxd;A&y!lW+#dT4+R@hCh7kHfau3;SXg z4#v~u@Amu~PQfB9!?V%7zud}SOnfgrGL-gj>44T&4!;dm6b#SYjHGjIrwK=)pBt9JtNRGf}gI0G-hi||Uk23O)O zxKVoc{#|?+AH%2dIeZyk!?$q{evd!nUzpU*pHBm9h==0g*c@A8H|&Y-{p_~9nZ!fU zy|3NUClI^$wp*M}JQdyh+b#V(;`z7;ufVJDdb|m5!#i*zZo-H0F?<@IL-#&-oBwOX zAK|C?E&hmq;9flVB!4{~iY=vm&-gfOkDc*k?2m(RDAxCEdi&C1Be|cwcS|<#JiGnt zzCUP}S?+s$HXOR|&-Ij6Xn?fO?gmS{H<}~uUe5$+6HS(OPE{;z45^gXhFP+^eSRc+ z*>k<}WP2`A_O{wO`g)`{fL4zno?5mvgNB@;qz5oNMiu^Q`@Hfwf;Qvi8fx)_%Ff z+Ao({`{k9^e!1M*FIQOm<&D;UxysrvZ?*Qzwbp*Q&f1@B|G&%HFE?2GfI9Xc%wyxwX#!|Gd;riLR zI2Y%mZF0Arug2@}MqDRt`>sdZlrG+cTX7q1#~t{Fw0`h5?!k}nTls`NuZq9opJ=Pv z<-6}gTe(KW_UZ$d-V~c*I=046()x}2UbNYhxDO7N)}MxB4vxhMI0=iT^}AB6#2TE7 z^KlU_!RzowT!m|JqqP3I2{+>w+%B#Ey6;b$JBfGU9%=pfBm5M<#BcFO{1yMi2I|)~ zeM4-7jWHctV;gLTJ*Dk8eQ*F~VUFC-?qlEt*}$GJ!O60r^=B-Wjck2mrEF~XnQ@kE zYJU$0=Sn+%%*REtg?&F6m&(?jcQsxo+t_(7u9EHSJ?6Mh+Wxy9H_C3deQ>k1{dWs) zm3I8uhTEm>zdLZJwEcA#z9H?n^fvC18MgiKQ<-I-v*WjNknJz{s~l|4<)Rm{*p6TB zd*NmS#lvlTVk2qCv&Ps|=Ggdz>C%pGt+9<9YwttCPIA2MPw2i+KEbxPVsn7B<6jmI zmXmD%!W?PG!?8F)PPXljljRiK{#YyvZ2M!SoNC)2XGuG5o{Mv(9Y5#eB5B9bCAd^p z+V;omq#ajp#8tA!wm+_uGi>|gMmfv2KW>(G+}(m(r5%5_{eSGe3w%_?**|{H?q+wh z2_cXG0RwI>NVp^<5D)=1gs=t($R#Q&H3>;zBOyt1L9kk*qEd?rf|gsAR_aTER%r2p zLh)_Ys#TjZO z1fM0gqWlHhh&Q491&*0ZF zJv_$oc)9}-U@j5kLB8N5;x3fGU;z>1f01A@ z5&eIO;5_0!l)vC2;*U`Ng5|^mD1X5)@e!22U;`2Jg=WE3#6u{5!B!&X4{HS15}!o* z3$7>r6y-0tnTT;=yWkEY#)F-LyNKxT_X_SKzJl@>e2j>B$05NdiI{&pCHO4yO_aZ2 z8xj5cD}qOfZ=?JLJBaAl-w`}cJdW}gJVC^Kly4tM89Etg^2$8He#Y->?bDUoG2ptWmS*S zAODp!`r%mWnQ0hl#4N1OBci`Om-5li-b~Cl47D!+`qiVP(VzZ>x6jl?2^Cx%eI#A3tv9ufWEBSiFrKPRI9dyO~`=jss`ApeM^hLPX{qJIk#(VtBq zqCX1}7o(mM(SJ1%(Qn;MT!Q$BRfeI~lP^R0l19JuMj=qTLXi zv9ACT{ft__jsE2p(&$$nAfi9{H4**D3F1xI-y#-x3(k!ru0?(j(N8QRqJOxBxE}SI zh<@O8BHI6?01)k8t@A~DSL=Dv-hWQ_2Mps+#0Ok4(GIecfT;hq zMAZAA5mDbKCj(K>0fuV`_Io3u&SeUnMf9T|6M7yIX{i;ufrvOa3yrK*?EqPz)YZKyN2K3;Gg4? z(hE>8iJ;#nmLfle{+x(*?Pos(|9Ije+?NWSN<=%)5_$}AvGjA`FD8w4Un>5Kh~+X* zfq$6v5}B8PUPZbJ_n*SQiHLqd%`f1;lXMO4KgIt5aXIGmLcc;pf1&0B;8*=9Dw!Jp zL4QL3MpP0H5VVKbEaN-qWYXwQg5sY^T!s5>q4SC8UkZdSBBGzE5;{z5m2npGR*}9* z##PX3Nu&SSA^bauYf-<1eu{WI^cVUa;yM|p5MGT_>t);lt;U_Z(I2ACF+BxD^jB)% z8PMgV(QmC4|8>Oe7^j8aMcje@MCd1p4`AFCx{Zi_P3;o{d7qHph4{Td#!uXXd5+Mz zMD%w>LKhSFp?(WpOZ<^xvJcVAMOxZ?eBtqai7o!h=-70LO(@BKiMYq zE5s*}e?q@Q{3*t9jwjGp?c0L>Ggs(*BKpx%p%)Q&2?FQGpnqTfyS0}+1;@omflg`PzGBjOi&5%D)6F8XA{&k5^|WtZzV-LS2g#UoU)()vSKHjC)~fs%~nksjn+Tjq5E7Ew665P+4EMv5CX z8e5H~H{Zs(WxaV-E$PXNS-hmCzPCV))fH&PTH_vTXrzxQt3rk0xK zYG=p8mZEaV&QrFuzOf7`WzqI3v%0Yvjj(=cO|89qus0qhxBi;CvP$swDyITX+rl=A9PRJ0*AHCH$EqEUpY7k|~PQO8y|2N!$oi3o8rsX-&sd0x|4(a_SM zc*?>}Wf9T6M6Ek4$EenG#FlKEq^?n)rqe^EY_aDK1L~+N>l;?vWZI)4h6}7?u z&R!C-qAJS8UZNK^dRcK<0eXl}4RmF?x9OFEU0GR6Q^m5L`kHGR(Zfc2ksce6#bdR` zUbJP&)%7;ZSX$j&8AkE+K4)pbP*~Aejb2kvFismA*=noHR$wGYs>+&IH}uw@s|ij; zEptG)dr5#b6T(y%v%82AOVJm$H1;ODvbMgdx~vY}>eAjChm~_IfSRQ>m6(9`61(sr zW+cbzKFgXKsw+>+uIJ3BW9p$&r~x`MQubKjibZ-~Oyass=Iw3Y#@CAyC{^Uq7iWO* zooNPG>|c-p)UFq`*lDTz4jIx`kg?vn)8T&(J3mxP@=2!=9nlpZZMO0!6`nwe@@xk0T5`22p&}3y-(D$h!_S9@#{UmWRh=UF4-gUKZRa5042V^6+_cg8{3IOg@=~w0zH6d9Jid;|`z`Etd5sW2y|vNu@R+5GyfKhRKFY)6 z?T9=+zOc)?76Nn{!G`A@mN^Bm>z8kn*AIR=y%`R9Ux$F6>Q%9WkMGRwbz19C1U`Gb zQxR_p;$u3JZSgK~$a@O%f^gGD%e%@UuN3k&gNgD6;?n8(nnNC+jq?4THrjfPL*Dz4 z_bl8fk9ul(-*(7rKw%WXO&cw5i$mUl>!S6P^+wBk(jjjjGHJ3F2Gr%oZ#wMxmw$b< zUZvXP@!JjjBK;8ekj10%h|&5TcgQP(ydb!k-eI`3e#ub4E|2eoa^bIy*00dP7X}|5 z(MF8sy8sq@I;s$_uFq-U*708LkoR}U!z0p&(ejo$0J(a z*V*!AxJ}*@4teiD9#o7Ncq{X$L*8~Z1ot+ z2z9)B9eg>x$a}%TH?hJjd*O>g0owDqxEH>lgO7Xd;ukSG9g`h=SAdCiL>tYw z#KCtJ_1K)4{h6 zd{cE|ML&{%1D`z|hivH}KfF~shGLRpFOO#-uc!LLGYsr}FZH5drGxJk@D))ZF^rd{ z419L|o`QaQd@F#z*6${VycA3dddz1BUwSWm&pPWzD3~css2p{pFLmRw3XXMkgM~h${{ZddBwJPbv~CnWTi zHPa^VR);+9$-KA+c{e%a#pCcAEpN6>-VYq|;*rTcl^f4ku;*V2_%eHlmuE8A^Cchg zvK=xVb8YeREC##0sgT!GIzD#Dn+kaxrzvlqP2NCEy6y5dL*6*}YoqHyfAHD$tF`6J z0x;`xo8pl7JmlqQVL&bKT!*|(HhHBsdF2jyoxP-&-`3dmI|O;GFHG;HHhCKy@=7sj zPKUoXTE9CS@;o<0+wUSU>+~LQ$Xf+@k7;4TM{=J-UMl2;;ZFUoz@_EA;gFY$M#S$n zv>_kOZyfU0Kpx|zJk|#-uhSu~6qEX=;IECA$9J^${F~Zps{298$kXK;hQF5gBZs^(xOsw8#Ay9~=#aPf#%TUsZIj1$==So>hrCr0X;!=>+Z^%^ zKwb*mnciAlTED+L`JLJ9IOa7HR_}&2@ei1`?G>aYazGI7*kB@Y`w>ji>_9E|QhrIV~@>*>2 zc=m`rU*ZSg`xGi9M&}F99I^9dflupBR?YXJgKtbP@_5#WU0yNx_?@XX+L{19h%^es z;}fJ~Jp!`6T#HNR%LIqKNw_&qWCUWgygY}zH8)4^r>_IAmbbtmuNV*J`2D*!THaiT zJP$sG3yOYUx5;aE$m1S-o3s$&qwEHUyv$onwSJ1}ZN;Vad%z*DExqUQ<9>&{r*1XX zI8J#t+2pnH$u|r-dQ|yqp6Y|)vG5>DIrR6m{ zvj&pPCB za{4*^wbA-L<&gIjKkwK(LZTWs=nI^>m1=y_hZ!y#`k1GFc?}aWFX=(QrycU*??gW&^1f}8_l`qe{G^`eO&tz-dm)e2fco(nyVfrj z_g7R$7eOxM(N7z#D$nep9gkO($p@c(JlA3Jgm0Yi6@hOz=3?4V2Co7~ydTc$IbNRi zLw>E_$Gz}f?cnPKUr+ii1)seh96-JVA)op3ATFIRts)Oj%J^p+#?u@C#ZV`j>m2f4 zfxP1dmb_i?*YegmpM&rEUtq3+I;f52+vl!HU zA)CCH9r9vhO=G@o!lw0m$sw<5fJ?2@rM&$%c|4PeVRCWNTrm{we3WJ9KmB<9*}?bn zMW#_t1~HoNGlzaf#rW=>2@}J7q50UMUr~z7;P=SX?_pdz|9BP@+E4?-(Cot@z1fyk z{WD$~-2O${8tLR=E+YwHwb6V;TX7m4kjH)7ABQ`VuHt1opvt=K!fG_&5a12aSsN{n zA1T%?%c&n5v`pTFym9AEnwWoXZZMdan`{4{I59sMoHS|tIE%A9aKns}kZEd3%;zkX z*E){%)kxC>SwlR<#y?!Su6>DzjY!yn!oJ424|_s=LgA2+#xTY& z(0wJXS>*HbWMqF#{%>LTadkz^gdf6c__)F~X5s^|dJOLmKm@(n_>kN1je%J2SXvQq z3|*jC>NxX-4?WCr)Pz};_N z$mK7-Z^CX)W2?e@ULIU+=HSn|$1}I{?Ops)vgDXyI>T_)lF<&m63lt-znJq9%=s~( zXz&aOtZyp=yj5Q z3?_51sfDt#o7?%iD|ux_Eq!QDgKIpRDQPNtA+7-%sQ6hbVqbZ&X5&z&Dsf0BT%7m-A{TYOf=Rz2`GQzLn;<->NXAZyfMNDChbJV(xf9MxxMWa2GjR}VQl=3XcLAKx#s(VhgvoJJ;$|kH z35mNOar6ZXYJ8IEPKb*mg9!#-p9uFP`1(zAW)j_F(~Ox(W8o4=GNasaIS7oPF(U@| zGy8iBQodCRTJR-6ZCFbQcql?w0-JSrg=`u# zsKr2=YO(4`1PIGm%JV_2`eMdqGz1x3hns(YG~9d%qQHuShpPk|CDPdDi;Dg~3CGdaWo?aP{v)A}fr$}13@B@uP1Thx_+)kU*xH&U@+soj zrp8KRY`A_!_1J6hVce>wvDef$E+1QoB@tsQ>YK(cX{o8L0=c3A-~Bg^t!P}4T~}XM zon2kAq$YbpS$_7o+`Nfj9j_qwym1r9meka>teTkLm2+%OU1eOsZORF=@~E$JX-D^u zanyB-%M6YWr>CXmeb+_GYc#%yR- z-N-fsm)e@<=32Csx~iIrI?zr*I^@#Y`ikakw5ao&>X$YLvzINag20QLtP2Hr{<69j zq$PVPOBvc?1x+KUr7d-pT$GZH>P_J%T+wVq0=P*CfwK7z@ zNRe>afy#HOSCJ4lf7Y@_Lw)yKTVJ;Gsl_b90pf|r%GXi0S81h_2RsFqemwPJ)=i-)yJ zNGjH8Hm|g#mX$TNAV=%*Iem9cv=loF0y2QgtCkf8GLMngqbyb%_|96T6)W)6r}p3_ zYc$8G1su^c8xpCZva5dSQWTF--%#<@mTJi>rE$-l_*g{A8|X@B)>)rnqX}7YQiO`U zs=j3jmU2mPsVI$$rca+7%wp3it*@_b3S!Mp5X~ewLz+o&USoYF77o-mHjVuM-LkAv z{1gmkfY&9&_fey|8u#$Wp^q~UZ3y$2fV)?(b&5Z!>Q8`8MNbzi%^cbnu+aMU6*&8%!zG-vxiB znKK>BM5i94-T0!ZYk05XXTDj+t1SxMcw*a?pL4aSal^N(e?ZCOq{uQ|ecjNkt4mZ< z^1Cqs>gum2M3yu+o~YW(wCfXAhVSR_@26(049%P{)l)4?7XRJ&LaD2~{*kGdH956C zI9B|ay4#G~7+|9)k6#c+joTsJ-Q~+~@<(%uq1<@mO??t0B7zYcEpEd}^C3mlxbcO` zxG1UQoCliqqX1Wbl)rs;%y`Oh(VumoKgxTR&}=XLQ5tK2+K~TtT;ylT^hbF5| znCI}&gO6%oE)+fU!-el*SXYK+S>JU9kP)l}MCK`Pbte(=uqGhx%)0>iS^AU{Btj0$ zei$CcDtV)YAIMh8eOuUCTp7$)3t9U}^Er+y%`osYT$VY$- zf2km!?U1e#Y!qBAc$465f|~@l2<{Z*^L5JMGhpH~f-ejHPVhZJzPBe|s$iDj1i=Eq z62Z#_%ZZrh)(eeK?+u;>hfkc8JD=V#U$=_?P9h#e^9dQ_`*)#VCZc?f3jLw@|BZ-D zPeQj$xp<_m!tt35=`5l11xv(zJ`v%X#GPv@TqyK!2)&7j@LRV?gOFu9))uLDYV~h(Q3aLxDO?b@cg!#@@5dxg_R0jMg(8IV6(X2AoLm{ z__vDtgGAKlJwiW9M7|vo`dMPGVZ1E#uLa){{Jr3x1wRl(HBjZnK7-}SJ9{D@j}p^} z$j{+|V+0YEa=%b;y5KCqxq_-*BYcI>VZmBKK8s}e+#q8=lUe1??W@JrlLjiekfZupV36*Rmno>? zf!r~qfkWAjAU}@?xfc;3r;Ld3tBDAI2NC=#9#l#d55g(App{&NFQ8n|MMTJ1EOa>$ z@>U6b9T9TZ3cZfV^nRIrWg?4EZG&w0%}uP)*mkSkD@$}J?amUtU+nHDF+_*gURk0y zm)sdAvL}uR(4(#Li;Vu(otbje^93c}T8sI=as{YxYNPX|3J!L8J0OqxP##gs`zGvmd544t zpbYtFIKQ#W+hx;_b2u&U-(a`P>i~^r9Wh$J2jF6t_pD7nbPExA&%$*Mk%Y*J*@v#2y3pGvOQD10Ta_qh*f*AAS+Tc)6FHHrnqT zSnTOIiga`!k(pp*_ove_5qvrfW#CPcn!C|Xqy35r1rG&6~WCO?_-$LaL;PS z%elLb_cDjPJCN97_-ms@FLcP;g$em2Fi{@ciI#V@L*A>9M?P(|yrm9#9gtTJCd$Kf zDyLiCb_k#LdJKHqH34M2H2faTULFn5uN>~wFNjO)$9V+QX@HY5rHR;UQxiaVD}$jl zQs?Q=26>0ICunUY+Oo@719^#v07JGK!x=A}ly0_cFgBrb{tE8eXnC?BMC9X@FZy<6 zTy8GDV4?ZqZ&ylD=V2n>t|a2g&oVezdFWB^yW>~Dp@?iS_{M^1#`hd$q+Bttl5+WW z6Ff0@(b41Mn>>8Pfq#C)!OV0=KH^|kf{!?!WAbdTlbx@Uqi>I`2@$xpTFQz))L&#Y zo3zXME()svA`gxEOtQ;k;O@_Lqs(0xdw-7<6{sF<;?ZhPufE3WqLU}G)Z|}p4y-o` zwl@deAJp3)8+Un}tXP?i|IH7Rr*X3Kf6?<=XcIAf{%SXFwUb5E#jSc8JI&cf)VS51 zv7N^3AzE{lbi9R&+z+uIB;?tM#^|I-~<{^#f4$T?;5@xNT`1a`bM&iQu{I{j5}*K<9N z0Vr1W>5mQrQhjHA4lQD|-(1kzPOqnNah{@$_G7uDn2iGQ;QsTBhw=Jw>3I2kMTdda zcncS9?;}S0)xd@JT=Drk@ORo%{79nH=)(6J2I-#W7uSQ&J|8FsaVGNt?i+ju!fK;c zAll~x++X=gxMA9&+7#2<(|lkOJTO&?7%gvX{&;J6m;W!G4~)b2tu$XeAE^3*`M^qO z6VC}p5gpp7bkhP=LO@8v4)Y+@NiOjVEF3&o^Zyh+$pi6YCo>cBF&s>!| zHKQo0+&u5YWByRXVY9e_>ssDCb!yVX?(l%n^FxeLp3tDThOBa(xWVNbmE3+ss;hid z=&V(Rot`ON>5{mA$ESgLlMZKu_mroHmxq&zGRh|%b`@KfaU}TGsZ+yn`5z{?AKdZt z{D-?z*?<1)^xt*9)9MNJ4Q&YJWn3LPFBDX3Zzw%s-W46^gpF-;Lc@x3GtAw2;y3S! zjPS?M&wO)4@yrgbQ(nlMVTElwNS%V=n(*`#@@162`&QxNVWWl|&HB6RP zluuv$UU|&PM3pNRTx>@+C9bYeTR>qxEXnX{2Yd>^*6|e#6|Pm;lDndtnxM{ zRPdK?wGLS|Xq2ZdWmLh5jjf&$cpN&y96!3;+?^H4gT#4jJIwohC;jgG3ZFc2Q)@bM z$nrI^zSiy<>u=8p=Z${zNEK3)5q5uE+munBKGc<_d1~4{C;hG{T>(1YMqds((MHd2 z|Lm*>5t})B_G_M#$u^&&_6JV}3^U8uJ~}*P)fJy-QlK(b)8Lo%iKL|m9C-v=f!rUhj*8o+fYZ#lZtZ6Gsw6I4v;X{; zX~RPPZD)nohLS_Z=&9`&g_9a$$Bu8fC46@KJ_6V$%ml+&mGt z0TDN^xMi$bc+eHR{>aam6^i=?D(Q z>4-(@e9#TG=SJ0{ZGU}WfB7|}7j4Qodg@dIYLY8_dtpo{u5I9|^w9JZJKSiS%Na+? z!O`Id%8|lg!(p_si!TlTu5--}T>H{;T2))iI+A)$e8?F7aA9iOYn}ewp$E+zvu((# zt@|5?-GfzS3qn_fuKbE|cUq|LtO8XVaX`@PeTtJi))fBZwag){MdpN#W3NH`Zx_b4 z`DdktG}rrYtSNjK9Fxvct>7;7L`LhcPo0_wNA~)s@&+IjYn~tP} z46I)>ixUq|kucEzB3`3zExz@yeN5A%EphBk)ke`k9PKm>F$1NI; zZ^B`W;Y~rD7ZGgYQ5;%c3_e7RJY7{QiM*IP4aa4FWRJTlt`6g>If5&u5_;mUY8<+J z+*SP(cWJn*`VUh67(ScFQ&xU15q-+aHBO!t2<1Ln#jt))4P0U#g+1Q2axcK!T(Qh> zt>Rs_;l+^|hHEvS5_r4~I9-Pfe#7TsK6)6)bscYuV@e<-=(?A;*j{FcYcs!6FueQ( z*0qK9c>hu)#%9M%zYI0Knrv+0#|^;3=E@Qfm`tJ4m=03o&Y{dN2GkbUVgG`+5P@1@O#_I6Ys^hwPH{7 z^7~!OJ=yS3sP|X=g2?CLUX}68F`s8I{`-7HwLdadETCC`%#eyE$A12%Hd`eB!vyuY*EFU!iH$BG^t;T zT8w#(vLlyYgt~)yPNDgDq@J8m*~~74_2h9CWg((UP|-fFqOBvXqJBa}y%qEj75!l) z=Oxf*eafu-iBiF}VNq%a+{_~?_&;DB%3Q@y8S|GWPq`YF1BV2tIV>F(E~*`t0?RB| z&L&@w+f9Z+rG;Q|ZCD&!0Q@&N1i5kK)3BtocYgud%a$LhTR1L^RcpgyyUF5cE zK$;4U(q&gO@P3LqW!0nA;K@+@r%c){epB<`0H=5c8vHB+m09kvEV^;CZ zOtneVP*y^ATR~jrwXP{pU>Hv?OMv^ZOjyRyk^;*tS`uJk`#qcd!Kt7&gF5G8SYC%q zIWF@O*G+haJggjUZ^Lth_6YLSGuBv?Yzh9j%>29HWEE<`|9qEKvKVgC8^r(L?f&LC z*05%ek=`oa9X)vajr8^6eX0lVcq4s>cn?EjBaw^nL?fB?iMlzxc%zrh8I7*6R2ntD z3Z+?qq?y-8N|Wzd%M^C%M|eDx`CV4-%`VzIAty5t zr6Tk=_F;litmE@lh+@T0KIV3#HAiE-&b}L8oUy^as$R837{M#zc`^ zfO0j`nI&Yow?`K9JR^Oca6Hx1(-2NENe%(FtduJFA&%>`G2hU*AK8$1%Q(|u4j)buteyB>$#d1_#^M|VBCMp_B z)y$7n$=yU+HLQ=6oE@O8l02#C*Fh(zLNGhcNcQN#xS4&S7bB8?M;i3`j9GuBTMv($ zlsw4yM?S>zu`vI|lXeFiGM7%?!XS3nD@zY72JRef6!3`{bT>m+oykQ_#k;IXVrdm{yZb61z2bx;{P;u`fg#f(MiZCW7HV@tpqi?0t)(#F@K=Cmy*e< zr(;;*&C6{L`x)8ds6+Or$Qxd+JvrQFftPEXnR6E;@p7e`*}sA}FV_><+=Y&p?~3gG z0A8-YWN$|xUj8B3;}C{d>^nI(!i85Lfc2WE-%%j?8HmTexj;^Owt>MwyIw)Hg~Fhy1{m$5+X|p& zN0jNlRRMPsux(YKcN5^w1xQA!Y%U-h84Mk2<|QpKFB!Bb?(!IJxG*fn$Ww_pI}WZG zi1UR`Qx-@_*ZPw^Lz1dCLdc8~O!sh`A_#X5qvE~?I;s(Is2%-L*|WN)#!CFi9AS^_ z1u;r*Au(ESAu&c0!<MivtK4O@8U?wEs>aL~5 zFyGEFKN20qSPTp73{ibh3)CAX+g=FKF#lz-Mx$70S8HKJ?_Shm4nR}FZf6DUxcBWxjD=n@DzWY^-gHBKv*QhO}X#*hQi`6`xq1m-1+ z^;zS7T8k|o{42wfw$gVQV=h)oTqd4aZHev`muW0uIxQ7h8p^N}v%;1}!$!(5>f4iK z`WE6cjY|nEK)0?ve(*R#d3)~mS}Al2nngUpeJD%F4l(UjQeS|)Sd^M zGX3#SCohV^e`-jV#Ad=BLI})MD=oBHEo~m*v4{sO5t9xZYBs?tjzxs^mMdYivMwTM z30)H#R16CUmW0x%gauIvrFIF?EI=q!F6yw5V8wQ+oj2NLlb1d&V}ruSl>K@-M~wAu zKC&YbnmaS)99+mBg4JX$i3EVf3NxR;e6R|dHU{tRrwDY{F#~dc+qNi(x*Y6_;sT zM$o)nOVQ$85aqqx&KoVSVn~>a3lUS9MV7S=u*$OHUl|Tyl;$#WRc)4hC*+Fr6~Jq8 zp^)$&F_tPewM(@ZWwzo%$E2NzRsfX|bjL=&1ghqRRt-k_{j^*9(H1eh;X*5K9--dsOc|lT1tZD99hY9LTCw{#;;h^7FHEab$K~z<0|Y`gd;y;N4~D$zEh}l4a+T5{F)1Cfh(#9j@RV2 zHOj8O^tPC}=~cbuim_5vUH3{@ERLZbZR&`lTQyE?W;&tHaYHW$6HyU9B zD&qrO?GRCno0|McCpe6VdBhYHJO=Uck0twpDT}Qk@G*!zNXQ%Mh$dRW82i!%@!_*l0~xNaW3o z>9c2C9*IZ=#1}BC(wBv+Ya47k=qN3if+|+s3L{*PH{JHNUN*6FFP=N2TQp@w#mu9! z`Ua?^EU5QgbXK*ym!*B0F_Ia4h03SC)W2G!CPo>X&p}k<=}zX|{$!tH8U2 z%I_*v}sUf0NpzkQFq6x$S;v*$wWiRZb+ zeJl32>#~-MvwG~8ceBUZ6|c*8$eih8PrREMCfO#>?w)CL=bb=dLe?7JE#6yWZu6{l ze*+<1%M*Af614I0PN6U%xF+Tn&#ms;$n!t~<&#ev-bEB*uRhUvQ9@!@8ILLd;2Q5O zF}HedbFZb8;)IkgY2%#+_X5=Ew(H8fk-~)BHLZvt?DZ@J!=D9Ycr;Wki|3zy{c}EpB9=Xf3?xwgGAa4}&BMeMI)VT5FscZNc z#a|p@;bZiu;ab(M{Jy9sY+SqA)gSMKZH8-CyZXne_&Opyyhn~2H`cdzIwnUVvTw2Pk>1 z5gtBQj2gEw$iY8I@dqO;cgy|uD@b!dx+dleR0R^jJUnW%AFABsgB+(uf&P7C)cv>Ug2;uUpqt7mw2 zIx9-R=Ek!GrV!nR7&gwRajP$j?eyp<0h=4|%=l=X)roy%f3$~spf;4d1{eL=ANEK6 zzYnMl{nXQBPScq+#Ut>#wJ>^BWfJ>J6fc6XqHGfljyYN%*(2-ZGwyJbDs4&dV% zR2?I5zTk!UJd*S@>xB(*fzWG-;D3ZzXc*56@<}4yi-{PDY6Y(oTqn3)P=yB{->L*= zh#nVNV`TtXLU*8&1ECxTT&VaA@4^eh9YjRBlQ_mOb_u2csc#W+wqaZ?*a{@yTETUK z>jnKl@&|?H(`4?Q7*CvlPniWdYLHfYH;gw_FY3ae4%L)9`)vA86hxLPn)=WkQ7B}7 zlD=GUnP9EpYQe7y{#fuQg6zu}{zE}Lmr-0-(9|dDkAsH@5aF!sy zapc|>D~Nf9@ioDF#9tk=fC2LnaerFydGUWm=syUmWg_5@=M!hdH;{-z&n80tRKeMT zR|u-TI>D#*=0vz}&>aKQ4)K3T@F#*lBZBWmp?Q1|<*Pk75zdcJoBoZ0*Ap?Q+(QH( zzY-=sEcmqG^F)MuP4FFY|A2__CyA)1Ci0Bo1A<9{DMZ#|q4}X1`KAaK5Fux&;5P-o zFZfHrNdb zR}s;vt|TIzw+h}X_@Ln9MDRZ?^z%f7J1*{jA)@o)dU5h`k1@*YFZ58M(}m6!dYsVb z3tcGm9HAEwA-9H@Wf(0&uOp(r{g%)_B%M%bPA@g5XfW(So@|$elxk z-gQFXCiI;|#J`1@hP{c2koTCl|4e9}=Ssd`3H^J)j|6$1D#LluM^Mf%BH|lEM7Z+> z=MvAsZ7dP|*NFSgM3lo?p*Imx4qJr&9&r@j+6nzb!G{G83jVtw&l6?5FABB`9u<63 z@DGB=1V0q~SnzLx{}lA}vE<@|Q6(QGp!#QYI|`8v3VFB3ej8OxA@5#DX9^;zik>WZ zf#3|mnSzUmsB4P_D+QMc)(JKWs&N$j*9*NyaIN57f*S?53f?EUPw;@?6M{zspA&ph z@J+!E!DE8&34Sd2nV_HJ9rTMAOcER8(VZ*3h*t)C z;9xe9bmkPFO6zaz+nVw~4~ zF6icb6||Z+1N#X*KrmG>D9D9nib*44~Uo_pA_sA{9KT0*66S9H-LkMR`(sCGlk9)_akt>PUu!au8Jf7M!{`@_X|EKxLfc?f{zGt9Ua3zC)g(V ziXa!((f^nrm)4QyB1@vl`wn1?V7y?WV5(qHkW1otKQLZ!vfu@R>i!7+r9xjRSSGks z@M=LWp`*N3!P^ACDR{Twy@Kk#3jBM8{;}Yrf?Re-c`pjSB6w8rcY=Qq|&9}W^R56vQC{+CMx(h zB@HYfLhm9$r5A*kkOnIKkd9K)K&2-lT}&ESPK5j_L8Uj+S4$e$Ktwv51y>P~-s=Qg ziAeVv!L>xBf1TiZBJyFA;4Tw1^j7nB==~Sc(39^FsGpjLL$6BG(CaZG^ynZ$k95w< z5Pyh>c<(17zQ>7(N9E(Wcn-k$5Kk@=gc8 zMCkLZ&@T|7*KwiWCqh4UKZWp#Oc(UbB7z=6gue5H=E`DKPlT=|W@3C2`Z^-(&zCv- zgC}C_aNZ%y>e4fWdNH2(7PBZr?)<#c_)#qU>oa+kMZIgRxy5IzaY z%gO7F6COPM#d`1auQO24c+UI`lri8%lf%jZ%do#-U#pErEHi+1zFN@iOSI8^)8K&a z#wZYv#~{!TJNqMaOKLnIy$qLK-XYNFh9U;to-&pAx66CdCJ$4{h`evYZkP8w=$_== z=8*TSO&;T6I;h`nTy}X!L7%{-jZW`_aIovw26;>?FATX6dDO=)?^zIw=paVRdj_;! zo`GkGEDy@VBfp5ecVV~73t}9Y3O8-Eyg$LgE^iX#>GI$+LY>}N2(!yu40(@fVZuj} zXQkNX6+m7w+^JtbTv{IceY?D5cx1s}8(qE}C+zap+VsP)6OlLDA#W<=ZPLPokK{!T zdFvrhm&X9%WBThH^4c8wFlJLEkHd5LhR%t5%wM|m3@@;c$6Wx(6e>E(Ml{37k` z^IrIVC449b%b@WvpR}P2n)e)hvAyu=ZxzN_!ML#BxJc{-%HySWascXh`5dCBc*h|@ zS_iNjOTd@N3MxkX@qMDbeA|$JlhAOPe`n*;`NuuObQp?g?2lD>I@3UFKQ8RicJlH3 z$b2?5G1`x35!&PR1bWMQ9PD{jPM#n>5p!J24%ZxU@Vz z_tar1;)g-&-8tIp@9%20b!}wN+T33Dtj*0E7gXkp_q1P(HUtxcAp|B1dUZYHW+hzX z{|%ZHDF!6W^jd4S^cgqmt-i~*7Cc{SPx}{{Jlh5*|EtfqiF^nBuM=#(oMi*Eu)rH`t3r&40;$_V$ja(waYDDWCPd6gn@?y?CF`ISvuG~Hfule{rfqh<30s=#M#AwlM2k?p*?#X{ggo^4;e%tVF zT!%nU!j1Ptm?o<9_B1cxeFu58(eX<2tkwJ3fAPHFKkw|jEl|dJ_T5jQSoEx$Uz2kA z)W-#$nDyX4v$JlVXY&4EnHPM)=vIrRQU97c;1OLmGOD@TQqvw53gQuEU3FDZt@=|r z_rH8npxZLr_Wz1AZX%ryHsWTR#vl7Gj_3cH53m%!*qj9xmOJy0#=7^i?EKebL>lbm z(_@R1PuCsJvp8;k5g*4p9R^kv?{ZqiXg}T?+sEZ1j6eSq^MOPE1@nOpok*mSR$k8e z!0Tr?ADD>@Ka=?Y=QU?CANVq7-?7bUqmv{}v$@-R08az*a&zrZ3nos?4+irmj?15P zhR+E$?@_Tuo)b(q&Na*;BV%o$tIgeD=KlRy!$nCrPr}^oQRhhn_a~lQ(wFCHxN-7_ zxs9i|xb`I;?tC~VgcC2ar?nYlirPknGs0U73)-&^R|2QDev%#$;WtcmR(h5r=B zxi0OaYBFlJ7JAw%YQi=2JH9`Dtl5?{c6fU{&dNy2No&sn$L7MJ?R7QFYOuw0VSL+< z7av@Fd4abrII@3x#)+VN+LXbg`y4gLoj5k?hKw7w7W&$MP_wh%|-Qc|vE0cIFxxeL{DKhTiv9=c@Iw8`UWy`^Sf;pD^9y%RML884;IHjHdDBn>w?w zbxPr|jRmiF8o{JO;< z%uI9LZLT*q#+*Fl@^15OS)_8N^TGR&t8?x8jO~3keto}jveqogWsdp} z#-21|eK|32WrSB0v&=He+im(~sG5*b9@P&n&@ZF>o=8o=sWvF}g>Cml>H$u-fy>2h zjN#@`F3x4LB)`>}x?@VmsG6FZggw5KhXV9p5JI?q{zy(ze(QM3ADQID}D$|7BDAl_I+v2wPH!o0SYGl38_VZ(p{QXwcC?kD-Xp(YWwg2_b z-0wV&96i}S0B1Te-!jS{Jf_kD+wNn-x4AcFZgXwyv&Y={VyCgbDYYh~BuDIVI z>~pAT44>JCdXL&?zIEjc{~OMD5>-6!LRt)@c_7Wbu_=`j{p%sMHFleCtEE%UsXiS# zPTv;B$e0U5O{t>s!OU%=52lCvpw48V&iFb;hB89qLc=#_etXwNM%Kx;L8_#2b{EbD zLU~_wV`$yJgwUYS(9ptzb7ons#eBV_czwsMg~rEsw*Kwdwi;t&Qm9z`PQGz#;YY9K z54o{uN~j3u_!LY2{SoK*`~m0q+*lNIGSwAze+}-xdF|EC9l0?ZU+vtU>%sr#TsQtV z<+|{{KG($mx?E!;!%hk1+GIX~um=(LF%|ZJ3cF8*-K)axQen{-N!avA*nKAr|MoYE zW^8>8?JY1*>FE1`E7V_3y7E6^xjp-y$Mb9vYQsHKLdmvMiB5g?^@r9J-tgJi9?Bfj zm+nPY&Yb$JQMuPY6daN}B%XPB8}br{XBGv4TrxPkdYT zD1o-wp#XH!+{ckie?rb@Stlsr95K$Zeu;}Zy{h6raq(^Y`t6MgtqpAqZ91OlJv)@~ zVjdB~elo~v@l>Yc9*Cl#8Zl(umpU$>SO3O%yl%rMgPy@@)X z4By1{?oGzGt_&4ImUX695IurNPQUW$dW^HJSeMU!*uUMq$+z9L$-5mI7_QkYF%L#^ zt9&m0WNV|rv)GO_U}QJ47Pfgpo|A`EKfI)F*8ap$FzsG7##rOuxX>rZUg=yD?9C@R zjXsHKzgDBGJ_+&Hn}Mq{LL;?5h9j&t_ZJg^`6oR<@d+dnk)*JG4roiF!v zXRb-^bvIIK4#vOS`Pj&Nqj#fkqkm)U#=yq7jqw}%Y{b;?#3eWOIXTH6c+V48+?hKk zH={6gdC0wsrNpqo{Z{_(DVh0u_x86?Zcm|K`^AhWPvqZNQuI99P;Gfy$cpvmkbC{E za>ko|V|wU0_$@A)ANr1JKeZK7JaFf>qUe45#+n?@C*^%7g+2-D!ioPZVeT~JzGXVXiIQMPa_CinFjU^v- z7-I@fe9+4NC@RIsDmd{6xMc-m_AEfX)6(hwo7O!w=6Lt$Jr$m}tQ3E>q^%?7(|emR z2l#YTW6Z}RlVZLpE-m7%&&b8^8_yp3iCFW#_YjBZW`mWY@m%F!Z z8?vV|H@$1T+aP66RaYrGXLcfI?&xrBo4ubhYrDw&di(BLN?cyWS%qEZSKIg0xTct+ zeMi63C9dj-`**vzUk-Qo=t1o`Tj=m*cTpnDO+dKOQ?l&@?K^r(+ zI8gZdcf^z=cC`NX)TymF|E~3QT<9Z)faY0vJYR7u+*~EWP+#ds=*ID|PiXDFL7^K_ zx}|N#$OUc2sM5A?rX+QmCB~SG+sDYMeMZ*IwjH7GhRm^(UW>8Py~l+)lerON(X8~D zqeGUfHxxeT+2-9Ev!yt6YRFL43cTW1cW^*Q;-@>y2DBx9x~43-P2_ANpQ~fwr|D(> zHfw&lFJ$IFcMLfnc;;Acs9y(X6u$PjV)~{WDG2#-5}>yu81i&X4vmx%*{{bY+;pYl zYGpr(i}zq^y*2Pk5V++tZU?F{1E`+sx(p)-_bI>v;9OuUa4C>CqTeLqI!J_oV?+pW z@x~qka)?2E_dqPbw+h5o>*yy6NMNK8P_EEp@YoRwcu67c)_ZS6Wf{m0Os{Tiu31`B ziI>a4nx?o%4B4l-YK#;JV;YnoR>Zd1@oNtNMbqTiD0YAUs| zemOEI3pzo$is1AGB_q4BPp@Br)A53Hu?t)-g!K!*>50zh0(Oel0UQ^Q?4mLv( z#D|BckT-p9HzA0DAu8(|8^Ke{^A^?f(86_u6M4b2rxYO7h_!Z|&a`so7A zn;pc*#=)%WWkGDr8C=;EoG~5yy^Z|Rf{;T>%908^k#A{SSv^JxY_6|oTWf3EX56Qk;n+{m87o7DP4jxm|tUez9Cf8fVe}v9@4mxB$WYq@W z%2dapM>hTU1puy?4)*3QpIU(KiAljjR<~NDF>N7&;PseEHh+xTNWt&>1w?v0G2F}t ze(!?Coq?|0eYBq3e$Qo)7Bd|};yo)Lg_An8)UzrKt959pXEi_H;i09TYssJwEp;=H z=eo6Uin#;UM9;bp7>1iOdhR?7tKt7E{ycZlIUWacJqvV`)w6-t7#<81^xQiILy0=- z)U#QIQb(P7w$L7LN!Uu36#qrg+Y>qJ^gk$#B0S%wRZblpaSvDn*YK%$;0Z)!2A;>i zEASfr-GM!fJn#xwVgd^x%^TpdeP4i!X#IiJu*V{25H@C937FikgD2*EzI}|N)#u@= z=J*}>>*H~AWwAH67~II%PDu87UWE_J>uh{y;PbpqUbN{F zQSQE5o&dWCv6sUwekA_fT$${<^*mZ9;LraAbJiU|9R6pfQ8>47@&Dp4aE;jwYl{D+ zKar0sjr?t4I2&Fbv1-|^BUUZD-~TGK_P3MAI%3tbTSu%~_GH6Nq5fZOfXo=~4pR_2 zeln8jZLGM)h@H>?XTx8CxMI(xJ>LHoJY&zJ3MqcB5{{ih_gqyKV$WyLsYu^RxVb4V z_Ci`?-iIci#LnPpmzLyOOADaM8vj@5eksE~<>y-D*hRFrdC^fBv6s{S zrk~$=#$LgidE7sg@m|TQ@MnJw{$m%j#NM}3cNNt?fz)vq88?#@TTW|VuGY;r1Nk=t zRq_H8DH^R6$qPuvF?oUWtmH961Cz;zN z_uxJc7k;~$zk#c0O-KwZe-V`b1+uL;j4+55Z%P7nw0r#f7=JzOet#Wvxq6qDb=*Jc5EAb< zhj=dpmHZHtGSBj=d`YeWmznB)lbRR<)*yOwCw)vVCm#4!WPrI-Sswt0`90faW2~J(~(1_Hm)_ zS$Lw1g!=Z8r)*#XPh zTqSWf1~-7oCywgY&D=f|NlRM^C(58n!!d^QStrtPrQ?Ld1!TFAUOo?(3};YeW-62W zTSiBdiObynL&`#k-_o)dPHE~4%ikRU`8-K=WMu~fy@xAZ9WMMfNp2Zp9XNntpt51hoTRSLC)&Z=qf_t#~^n` zs)jU{_hiRFeHnJUBdrg##=Qc+a}hZ1892D+$=IWCtcFIIT2*No)ar*UeU4gLaD0gl z8;(ce81Je^M!<(NjtKkRAL*E)I+59MFcwxXnTdaIq5-VvDA$!19EmitI1Z2IDr)wX zUcoA%WAA?u!Fh6YU71GrdT7eb(Y{LLOCgVGZ$=-vT4LV8@XI-Z7@13qQ`e4bJALfhA7I+sGPTEjO7=3w|5HSv*E2a2(;reB1le&;sMQ76I2E z8OKEkmcvoVRl8C@;{OAqdO`6|rmvZ=a87t0{@glQ%KhhcL(DhewTmYH0LSfgq~o}H zn+~o(kb#a=I2?|^KC4ic?%EeDoFa0laE>sm@NbBk`Vs#hh%A9$E+Q431&6cmtJ@=u zaPTA8MIGYvjqQ<(;aCBm$klLM2FF+qz$M5S?weTl<7tnhaE1IBvb}QLN`UVcSYx?z z1K(C;&Dq~edz&?IG5mgv&~aD6!6nwLf}!|lg`t9DjTPH|r)?Fmxw7Ed*Y&*0wxUh& z><`a^op6kR<8%`m+;{8tR2+_h^AUCn!f@-sT5G}r?QAA|7Z(Suoe!np7AtSG75xU( z*sltH4MzmFF80~73Q|$yQ{el6S~;Iqg8S}gI#o``H*Hu-*>}(O>+I9;5!m3qJMo3< z0{+~CCHaAgNkJt%A44V`G%1Ic^Rm?JM0SP1dFWFcp&}XNyZ;sp z3^%&Q>Sy6es}o&MSe^7$c&=2BeObt8 z%*R=wFM#9N$A`dx^zt$|OfP56@#wWzhn}Mvd-)2gv6u6pu?oiEABT^35YGDVhz}nH zoz*X>+BjA2Gcmzz8P_*qgwp#@c!IQmexrq|k%3g)e zWIEMW-Le6GgVm2C_!4`jRS-bk@-&&}Q|=ExrnFl9 z&_z%;S~fn>X49fmvHNu3l$@vfKCK@@3p3Rh5V8kWWTx8FDjpL=BTO<^83^Bj-QM4f zAF`URFe#N?foq4Dt}rQ;UEwy$(iJAjB?;F8G2_|fRE|en>%(+~sbZOHdrZMSKFdBm zm9|SMqcaqX^$RJXqf8Uq4?rr2AQ6_g0?P5@Ma%nR1hTx_P|!0~v5OKPv8xhhq8+f4 z)en8S_-^>y&wJzl5sLfII>qhE&&zoEJn~@1`xiv!S=x;EFUokooU)AfKb7(RvyjKs zq6jaAcw}%XL{l9v$?)C_N4^=}UzXv09%UKcUy-zlhJ8h zG|Uz9k!8&OC1W>3Gan3wpjEi=@Rj@~O_)}L}KAz5f z(BaTE)YF;B2^*(4qn<<K`Xn!~Oac_rm>l-G&;DayacKy0s1XWZK;_kn4I3NY|kSA=mF6$)rwryci03n0tI^KkK85(tIO#n5#KDB!@|i6WNx0!!g1 zfi)Vq(gfP2R&=Es)}&#Z<6-R@7Tu{~(cP~0t?Ki6qb-#dWglfa7(iGtX+hqJ>d#iS zzaMBID*NN=Le7ET53nI}<^1{m054Dn@Wzk*6pt&tKk>9g8Yow}KQ#Ur1b-CxIyK}X z-na+7#+d3J&c^?7fS1vOxJIw*<~>JsTc^B-ZekykEZu-C^@G`CygkrQtbWMs^ut3i z%l?SLGh{0HSE|pD%>0dcMEU5`e*%>438s9nvV1T$AwX-nVy#e0XG&cpr8ak8CP@^l z7+<2d>{lGx;>PtP?friog5%?h>W!ZF@e zjr;*Vhv8H7H#i(z@f4+_%nq)EBE8|@;29YP#~W}Ijg_FUZZDbyM_^xR(JbMDvFr!O zka{V0yPvaWAku1wUmixcagA`yp<^{1O>m5NRU_Ns^8kE`_Q2unJGi|dh;s3U%uJZz z5rT~HB+j9)iV7S7L$_L^MnUgDI6+5FkAV(YvP$;j{|5F}X6R<;Tg=dRAw17~d>xMW z==dTWJWY17_gniloOOW1c{c#2;SCZ9%$UO`wc zj+d4GFzp@zR{DFI$j;*^uzO4Yf!<%C#}eIO^rUh6pxv49SNw62@Y_h3%VK-DVY>tqOf{Y$kW@Kxp@%<0&V_V`F+-Q=xv(cn+eP zVX<3~!{Qeqn_;mVE;udgmyq-C;8~!DSURO2nb`y6g< zv3&b#tb!`&4S`=z*foAQ8Zf~@H^Xt7;tUo?HRpnu?_g$v*^c}V!J<{L4$*nCIaQ-$ zZePHpb769dXVMzAOZ_xiXpMo-1ZXv=mP|HH!qzApGGdnM=6aIBydi{{Coc-FM=ZG% z>SIkULX+9UQtyVBnVDs=dFE_n^)2V46yrN*d=@-5`#c7-dOjWZC_4|6E$+dG%eZVM z_pE_spNAptY46VE4MpzwD(u{E!i#$-+b-iGi`-Kh%XrU-d&4-K>Dav4(Y zq0{WSsVFJ;&>(y6ccIHYZDC;U>G0zo8fBOL4QX)CoLR;h1NY38WrI=G+%xOSCc!Xw zJc022zISQAo_6xuAARvyZ))c0nY?%mj3`8;;@u$j>ObO6|t@sG8nTca^(KiYcy$)rLIF zsDYlo3_$EP3hmU}%VP@j*hgceRP<(EPKlrdw07Enir!%20v`9Gft8z+Q zd4MXz9A;OAMp=YG5NKJ1!Kc`a!wg_iXzC8NZ6gmG4mpafgyUK1Y4=Jk?SJFU0gQmJ zgt%DeI()FzSk(HX1u0hELnG)3yTr_i?I{tBFW% zNBhf}U~EiWjfsyP0z*_-p1DG57b{)oOSZ;mB9UI`&5=U&i6UXkB#d>i-KwFL{CG`K zEO2wk!cT~33SM;-N)pI&kywUfBFmBATgoxXL}t{<#)-jBYXD`V{i(j>5c_nab}eh6 zIATv9V6w*MN+|lYcrfRjcgfolSYxP5s5 z4sXK%1cfC8m8h_U&lmA19)~4{yD&WPNHymGJ#ZavJmEqA1N5Nb1Wm}^hM|HPAZWm` zT5PezNbtvhZ$s76ix?@+8ZQVA6S~9=H5v6QpvNJ46=8I%{km0NshJI&_?Z+c)e0LY z{(GCT#5cdpvrlWO7X*h1T@nxVvN;B!JFq)edzP16+_NL@xmq=SH4yhY1A(%w#{V7I zZF!~&hk10m77SQ<2gn`RQE2>^Z3F&q#GY!kS?5}(9iW@@lWc2?)oSHjXNNu>*am<4 zU4*?aLS6s3#%Tu_wgdY>6P`aTdND8tS+t~x;1JQG0Bf(d}b+l-NF!X&ZW4PqP9V8F^hKu*RULUk03MO`Em z0vEo_CK1MNdKg`!uppV5SD%PS&7c|hRUyO)ERx0%MPB=|ZB>Wp|EI~%z209~({ z0OA+oTtXbhZgf0jaE!!`_9EUC-7^SRcZpX5#u+WTRRon#FZ;K<+KzSM{_Rw9w`@4H zfmHcUzw(_4%G3y0`@}5M4#*dGTvH}Fga_T!5FU(&qUs?a9M`yRF;@74)qIvOI=ip8 zX?PD`cn>cS4h`?)3&$NFvwa8IeGWUCmUaKCadrYnjMG(w2IfjsTv_0SdJTRR)b?VB z8R8akt|Go*d?9&vyGF3#Al837T`tW zd!C2DHSh0O@%$urC6kF2@l0$(CUPVbAxUW) zGLdtD?opD`a)R}diU6w89hIO;Chl%M;6T2J9oW0}QKPVgXu^)+nb?7yx{1Bf=vKvb zSNL@k`<>CPj_Y~{G`npfc4TWJpgrVFIM*3p{P#A-$2;Vd5713*$J)GAW+mki(98rg zBL1ManLJ40OW}!`4KWjYDkdPTHM&iz-q{#F=0z#XS1H~Ulc8bk$UL!HoJ$GzYxolE z%&16$E!wrxM~K1_VzoGz6LsQTLKq9n{T33N!dR$^TUZshP!+eZ%5NdDf%;2o)dZuW zatM=$YT{1gOWZ5YD#GOK48Ps@IDl|b;F;0YNIo-$pu;mG$#E@!1B|3T{eAI*@bWed z5Bb7r!rL@F%NOpQGM|LjkFcYCT>Wx5R*Tm%_MPXA6aQt)!~e_L-sL zYVkVb#C2wjdp(SCI5zssK=O|lVTfIOjczJ!5nysKlo6DV1gns+xQafGrs73Ar3QMY|<%-p;WFk zUc}krTt;j#zQk7JOI&Px@n5!i_+O13>9J#NGEV&WwgR|NJw%~H=NSawQ-v?V-^Rk1 z;0?&G70g^?Dowm1&Xoi|$w%EK2k7dH9TPx;=1o96p(RX+9|?vI;U<*WF^j}{6|qO0 zH3Vmnv{!Y2u1}c&!p%XI6l6q1ipO8(#`j-iF?f$?{x_?Gk8(@} z!isD(c`{Au#*8-;W6~GdHl{3V2OPVwqdT#I?lI1nfY*$Z_^mis5>TWrVJ@Fn&V%!8 z<4dd+XAQC0_!1Ww-;02~#+SIx_!9RRUxE)EaikMw)?Y~+HonA*;;bah6?zTvj`1bl z6K4%^%=i*$Ioc%x*i)?b9pAMM(Ah&mDhWPNgc32v_!4}S2w!5R@g?~95WWO|)`n^! z_{;;ba(%^a(S&j3F#zQo_fxts_}!&UMi?Jv$6HV3zj z*l)m&D=*?n>}l3{Jm_)`P&g`KD~MZ-J;K;q!QT_orWYfgz;Z;8Z9o3sf}NA$ZJ1Hf zeLHrPg5X79$l{yW3}lLGo2E>E^DcakA(R~l$6kN$(t@6P%YxuE7p5b?MB_xbY*a)L z4hW=nfG$TADv2B~fUZ+b0KxP$hB0FW;X@@f8RytkV5ioNZy|gZI}Ve0Wq3zSJaln_DOPDL3AX;?|(tA(ClvI>Rbw zD8HiQiJRLI1NqN1BiQq>7l@Df=XP_qr}~2A(uwlFBERzSdg~!nVZi=Nb~nq$hOA(> zPq6r~6>VtVR3F{4rfL1ww&<4T)^nn@&2{zBHO+0&wH=Kc>mY7wY1~-f8eP-6X?#<2 zQ~mh*HESEk7sU$47v$wnJa>X1Z%V<$=z_+kj;#|56E&laO|=_4U~ zH#V+~uCJ|4O1UUf7|D0jw<6Kw)q$70we@xF8{7Uza+gqZZhoR|+x{0*!%VvkMNE#_9tQ@SLyZ z9OFr&aTm;QOpvGz6L=5BIPe)YtN;Rcs-)J~>^aeZ#*Mj$i~!CvmOb1G1ntx?{yUM> zX#pGk*$wTq?U7?fmaJZgDN5Y;NVZ+VIC%y9KcD}Gl~gz@BlCe#>!ZU;9Q;14BriYe zY+dfWYeg1H63&LmDyM%WA%UyA+mV7X1xsi{vS6oe|7cADBB@SuyE7ybz?(5% z-X5{-euKiNmN=)}5>2pqsJmV4bdNaag`F*7Cw=*-Y4caicYbwl#Ob!vxheaW1<~2g zpuNueNS>2^i*sIa;qXSAYH@#36uB^^}@&Ts~YXD)#1iUlhc zlsK8|oPFDOu5{kV_t5=Wd8~(BTrzaC$!s`veSY5XVbex1j`LItl5Kas+guoxixi3Kw#Y0g{=C#er(>_vyEruQ zFna0N8j~v-Bc%A)ScE4 z`$AB~b9@>SB{Y7nb--kUC;GK5rTC46pP=n`f@ecTNvGb0Yk|x4GCk+G9Bw zcK*~O%!1m^q3yJ5JI`6+95@0yoQJj-JBP8%Q#NjmAtW_|x8D%ZhSyY_ZBM@BWQ9k} z#|JjzDLvKG9)2r+>K6C;SueYHg2(H>O@l_{12o`U#M_; z&&!{FXo52^?5ryu?hFW*lsNT~(vlfbr%z=1!r>zrRV%2gQ?zvP7JHh#5%a>kX5@T)`;=3quyFLbI$CV z1=X?2`LQ{(=FeFXn_X_nGFq)MuC>wDv33L2Z;Cb6SqWdmq^Y*X^Xg*_^&4C8a=06a zY^<+ukIDBy*KJ(0zRe49PYE%zpi+#h3dLGlo7drdZ((tz<}LMgu}yXH2%GApM6q_O z18X43;!#|XrirD64Ote+P4>L{)@J0!V!AN8*+PUEmKt!wC2{|EK($pi$WBe#+L7~-xHM=|ms9mi+R)SkNobk}cP5fjjETJZAO?J4vmFWgnE!KOIdU4}O ze))rg4%F#{0#vg2XnVx86z53xS(nW%SmjJsx{9?o8*}_kR(o^%nvJn_YtV-A4x)X4 zC;NCF&+)RjY0XyTs=a}~9#|LK+`4X?`4WYER3V|My-tR%Y8`Jr)z(@Yb!#3|jl|k3 z$}jMI+}<5;C#^>_N%%)|qj(We%~;i~E{1Abhc0gx_(D8}{R39B8OH7sssU z*=yD{ZiOSrrI@VxlJt=XZl_O(jHj(%kQyh@uE2v7RrkcCOCYU#jYjT=;e!jpX&yC z9&Q<}+J-f8ORldu955d}PLSyl-iWsb^HmNfZJ4TZBH1McJ+#&~x3@QMvd}5mp}mB( zf8iH?)c;BNa8Z|y0N_M zxCeGyM`L^aTAnR9Fg3NsWMq&-RgORJn=mJ`;I$ZrC~2`Siqfml@NM<&US;xB;*RmM zUR#@I2VDWjM>P(S%Ia#19i{~XY*P#BynUVYU<*s}#k|U8^`UZQ`2Wv0?~=cHXDZ)Z zUg8Ak9zQt2;Ou33Co52T7fu)GwXt>0tytF)$M3l@4lw?2+i;kU)$&B97Q6H(y|PPG zkRFbchX34$ywDq~WwIp`?73go))f;q*OvJP4^R1$s@sFjsfmZk`qni~b?z((>xR~0 z?8A}hbzzwU;45pJuwV?A`IE5|`tT^Q>KfOr^RgiW8PA67ei*BC;OTNSb6u2#tg{{y zh99wnsx;GwwvO7``nGsqH>dS{ukS-%I6Hop60tBbw8&(_j6pGGj)QvqfK51Ix_Ltt z${6g*D356qOp#y-f7Z78#wND`kwR_z*5kE|&Uw6i z$v7N~dGicko@8)mo0+Mr8{(Z-*!J#Bp{X9zLv&+wAd73N#yVQ$#OOwnKEfg-jDKQ^ zK6N~eu8|&qakEP#bQPq;Ih#(zWUhw;#GKL0SD)O;s_!gWRZ%%-;q3g0dD>gOQZwsv zX4Pz>78;xUEsN>hgvo`8IdKmJ`NX^wh*_6LU)P9Mi`BQbHghI)uFU1!0k!3vHk|Fu zv@_{=<>@h@Cv-W0Wjbxmoi%G}IG4j|O>^_cwlKzo@QkX3;W?}+tS%a^Y;9&wZfaLVa zgO@p%Lq{GlyWzZTJ2SiguGC9YE(>1n>}EJ0L%SPq=g!Oy(YCyc<@$Hxrq#^sk-O3_ z4PBOYdFt+zD}sBRE1@+byCv{e_Q-LrBFJ07C(zwt2aaYl|G7SW-YTA%9o`kXH0`p~ z%Tsm-uW%RQf8CK z&_=Q$#M%u#kK(AmQ`xN{vw!b~V9%v5@@?lYz&F}Zm z_?DT!Uif&RJ5ppC?3)4JWb|zgZc!%cr|5eMrtb!L3)8nbc)*vapJqi7PW$Z70fhTE z2g{2l>Ze=Npg?{0?*PL6n}gp2Bc-1w&@>5op5$0W()l4L$ai*Jru z-p=!I@NkXg;jwJCLf0X5h40Ib?e6z}^eT-$yEQ z9PfqWYghmd-57rYWa@{p_rmcsUuB+Cdg1HLYm)REG@R#{UN~MZN(#RsN&b}T^Ssjw z$A|x&a;ASUN&o9f^3zH3ktF%UB$=;bxEt-~CdspsF*dTxI5^CyuW-668^qqo*VjJ|f}y+sOFUn|qg3CV{@YgNaj3Z;I&7DdkqC z_;$Gli!`>iu89;J??TB0P3RJ2?ud-^-7-zO73WUQy~_aJU2-qX;#anxbTuiHXxEnH z-ko0Sb*3BU-eu}~A>zAI@Lxf>5pfNqS@+)*^QuoS#l0IDZX^lz--&huV6DsLizs_{ zL6dH^dkJYK5-$Cd0~7AHCnYHtldfM<#Ka4f_~ov-z0)O9!nH>7Rj6m$-0R{^IK5r1 zcYR!QUd!_;%Jr1ktf8cPXP&?RZiDB^djQ7`NVrTyPEDTT_uslC+og>qFSu?@&}0pX zDfc?t4efHHk{&Sb-aFUy&8&_cbKP zkPJ-ucowCcP0lkv*U6Y~-r~$yU|zS$SZID&nX$W)Z#Ri_Iagu250J3)5{dLaAl>wkAD$bT zuWylkdHw*aw0vNh%6ywBqgu-W{}dZT>)Z0t{dh^~Y_4$fw z#yazED%V?nhcf(+kRCNtN{0H35j{GSKe{x2zm$}D9c zkx^73vM6jK0<$OV1^}E7lE1Po(TP;8qWSlnb)?YA@zVc(`2=ouhk8-ARg)*kBSDvHfg5Qj{MR}p}66F=jPb)dTQU5k2=i-z(K9N6A zzNCC#$vHT~ae*yNRc0xBDf=rqN2fmfIa#D+f2X`ixlVbm@&e`M%4?LjD8HlRH^OM= zJtbE^qRiJ6$s8q*1Ija$3zRL&3zWN+*C}sR-mmGnM>m z1NAp6_b6{x-mCnY@=@iFl)qPgs7%EHN_$*Cnmkompe$9&Cx8&XO66ANPUY3go0Rt| zzpCWQKD7U9<$KD%D|yagcwc3XGNPQS+68_EyVKMQ%n+ilh`66xkD^OaMT&B}|F*DCib?;>I6 zu*y%V{F=(YQF0|S>fzleVLxS9S*)y8ZdC46eqH&r@|VgW=Ag9OO_`&dq+F#upG3W1 zM&g#?^(x;=qWpKMd{E`DseD-F$5nnt2)WO&M@Uj_0Lz9C@VC4 zk;*GnUP~gs>&O{6&#M1+<)s>alk#EZFO&`@wv0bac{YiBHIgGO>k<ccU1nK%Fn6%Qf-UQ02!|{=Ul3tNgOcM^yfu%I~ZEA&K;|ajcR#%CXAn%5vo@Wu0=1 za)L`Ew;cHEspQTGpRc4&cIt_1H_2- zDwil{ssAFC&mdvv9F^OZ7bF$FDO4y_8Vg2mni2dE0uN1%aos0eo1*)`HJ#&<@+Ss^ zZL~6?{!>&gQMp3pMJlgQ`D~RNRc=!Gd=lwgtNwSZd{D!`t@2NlZ<3SoH7I4TVJ7}4 zoVRT%&AMZc=tAw<#}HUaH)q z{FL%~&l0f-%&oH{DJbv%AYEKrhHxb8|AyoKPvyC{8*WWa}n!1 zQ`uYDPdQYXqa3XquPjtfR$AD29Tik&Dlz>Mf2avhRgP1lON;+hWr=dJvRYZEY*1dT zyi|FWa^X(IF8qY=O}sKlrn!hOYu5sRjyZ_tL#wjA~AQA`&=MDR!aF=y!=3bCn&+%anVR*C=mL-mJV$d5`jbCBLi3^bRY3to(`c z6{Xy#gC0MyNBuu2)cwN~|*;CnHIaoPLiIsvyKVK>L^ANvSxX;mHbW|^>-@y-9*Y)D{oMKR>_658UAJE1ImY#TsWKI-&4M%d{ucw`CBE| z52yZLl|kOWgUqkWka8ap3bEuT^=ya*OhO78|;iH_cg(6 zmH8<=`VUv;D#s}&C?_f9ekb(jsmyQWF+RUNN!BSFl+DUE<$21Bl>D?Fo-`?&C5t#Y069A&feV&$dEtCV|{H!44;yi0kn@}QER zT425&R`SEJl%G&OrF>q=udg%wP31evKPf*{^0iLt1(lh~?#jN(fl7Yshx(@~$0_ra zla!|`XDZ8-3zc#|8+MkfEcdk`^CNt;->lrMJWqMC@>1nh%Du`Pm7i1IuKc|6i%PjK zj&vST`BCK$mCq_)Qp$aD=>Jybx0Q0A9R44xoXY#skol~a?5ULd=8y-g99EvD9IGr) zPE^iRmMN>0%ams+`B8PIw@G=fatDcPIl0dcUa7L&Z->n99y*{m)d&^9so8Rc=zYDz_;wRPIvlR`UCTw0Dd0F6F(-gUYWeA69-_`GoQ*<+I8c zl&>l~mHdDq)B8aAcV&RjE8x!$8j^jLLzVJe1^#1HjwtyRU+Pa)&QmT@E>rU3zSP^G zY*KDk@}qzZ-=qALlAl4O|82^9l=mz7Swx0^Tls|YDdn?Dd0qoOekqaqzg51g{G;+C z<=>U^+y?sTxCUW7eqfOttmMZAd7n3`oT!|ttV`K$}viQYmoPmOONTQ9hykq4HT}r}BvME#`-2yl;>@Tce%>)+zm3n#z%X%DeqCy_sy<#{0VHml4p5Hj9X%4?N3D&=`0!f#jkUgZ~+UsZlX`Ka=7<9^^;~!GWb5O{Ssr&=wkCiVfUs3*2`G)dsr93Bv zoj z%3mpet^B?656WZ8zbYNvvthZ@l-bH&$^ptDN_j2}{alr!$_dJ;N_k!ky*Vn&b7RPr zD%U7iDPu}`ehj@0Dxa(DQ0`LhR(@J}t@2jooyspLzpQ*f$a_BS3akFQTc}Q zcgjC0KUDICOxg)5dnx-WhbV_D`598`7b^KRQpy!dF1b&+M!8BEQ}Uyw3~yClpxmLn zTzRGPdgV>ZTa|Yz`N>n-dr0}H@^K}s^n)RDGyNcOU#r{RgPEYD<><9 zm9v%d{2%cat6Z(*XDMlKy|P)^raVu1k@7O-9_2pe^-6x$lJ@RZ9#Vcy$&Udu{IK## z<mhwI22TFb$nBjJR!;msd$u9*nyq|KYGDnHqj20FGl;36W9yPq> zc~h9o)c2?{mxc*>9x<83v0h3d?Q# zLm8C(qkLyl23M0PXPvTvM0qzVrCca?J7rMHhw@xN8Qei4v%8eLNz}(x%Dp7&UXsyi+O9sZh>0_}mHQ`wNNkmGLz6O!VPYsEDj7$TOK1^AGIodxE7g0pcC6SL(m1mR4&uW$HNaSmW z%DYJ9Ps#~B@KK1L$nVH<@0ND}#%=bn(|cQGhOi-xz8BT>I9^Y{U9G;3p}WT(mZ`4@A6r z(Q>1kU_mc*3k~m5e{RFMzm;Pb=R>eqIxm(`lAh;gr3 zyOvA;`9is{pHIX>MosJMSqgMx6Q`@sMlOP^p~$@z!3xWpxHO?J);g?+1SKrq5?RxZ zs#)974znk_;n25mNLoBkaVs?N{$u!)Z8-i@55t~p$$AXqhM@p!*nhI#IOrs&+XH^? z=B8T)55L}Q$QXXS&DEO;pLFb{8nP8tz>FuN@wKdwYHM=pV$+{Cx(y-`+9^qu}RmuD$Ev;kS3I zue>-tc=is%?YDOUgid!6}61(4C ze^kJ7_|YD2k$Lv`evaSX0yI{`aqRJZ9>2X7*xRf2aJuvCotk8iziZinaCdX_H$2In z)nVph%wKQpZhI_9vR8=4KjIowJ&HU}`tz3ydwKAuJzS!A_RdeT$KSPt5$(5<_!X01UhrI@O5K%qAdO6A7OUxhqXb-P+diDay0KC2NiqBb& z*B*aQve&s8ZG?EVhgTdudn44ITdq=c_InWSZf<+TjN~;bkpKk4Lxt0jDu~p&%@Otec7=JVK0pOn*#rG?95*e>}(5PbgKr1 z9qDEsVXi$hiEL|)G)KeS^0B_~l*tndC*{MPmzU@JKXGDV80+KZ;Xk+48QbS9C^KKj zfI+dD>)EATlfwU23hRSsksdf>u7}HHBWT|QcNWGUxkv`Es6wjzUf2%BCVX%Zvbze*Vo#m}PMc;;cKqIegK?8+2;LdH|Ck4%q>i;y6g2 zqLjlB$7xvQ)08}?P_IZ?temBsr^M++^khJR{yLR8@8W&C|4;W@;+Lf6R>X-eX}xP$ zqj2J@)&J(jDYE^qx<2K3*5BVawx5ID-P|ztXjHdVssXbx=x>Fa12o5f?i_yEZf+bn zR=ep^h1-BaqPV48`IiGenH>?pJ zbhF&t_&bVDHxO<*xwk7_y;pEfIo|x@Lg?YV+ycnP_wG+-KJXYaezhA3bhAME=L1_| z?=bv$Ey-hwpejR)4~LfcG1+ z*s(Wit}q|?E;1IdLzlw`^MRjH3Zxw*f+^S2Gnh7u@a6+cA$6G#{Fuf2*USh0(MdaA z(Y0nuk#L%lQ`0|V-teDE!T-HU0Xw|A{oBk5{Ko?_FXw3d<2d!7xq;i7pUi)^xj`k) zMgNMq!IMb$pFKBt!*}4xNe9i9JU95oNzM%xo#fo$8I<_27o>M-*2Nppi@*yB9h z-P|Ji<_2=Z;D3E?kaVv==LUMOAaQQ637J2+djMDAe|QZ{?FXtzwuBT_4c2+!O7h>_|M$n z`1cJ?I5%joU*kSQ;QfG4nj7R#nR3$i4fyOE+XO4p`vw~uK#l~&kwkM&&fPL;B%0Z zxku1`lJ^J-wO;(?pxb>Z6yKSZ>3}y6DDb^WVBRV)?-NWZDljh;oW%PCd>G@K2b5w} z^&VdfmX#jb`(ZF|?1LZw`R^Ye{AkC~()94TJsx35o`eiK#1L!52>6D+wp{#X9a?oOqeHCFBh5z#;eY6B<)Sgc#7YXy%dv(d*0*VW`JuxbLZTJ?1J+l{**`Pz zOiqhk_|b2ePUw(*Xv~8xIhhriN2SHrQiFK6~!a z5eSM!7hm`gEY!IdT25P~6rtfERAN*_1{EGReCOc1SxN&9*>Y}Wo zynONd7q`yt%xN5RsCU`SiaF(_@1^xB?hK9&J(D^*^BHG!k7s*~?eomy_b+b^b@mzC z3$CkLozC#s9&qhzomerY{M63Ovc>P;&^n=FQu(mX#Ya;!g7|M|*!b^cgzlXzCA*|7 z7iC-g{!Oi;D)O{F zZfkhPGIbq3RQlemUVSTumJjLdGvexFBlEibVVD!V_UdD~w`Sef>vw6E{e??@i)W@c z_Wj(LvKeK0VyVZ2Hy<08H~&GWEL710CBNHEtxs_fmwjk1}k_3BuT3SD^p)EBg%kZ~5LJ>Sy?&frola z|4n_i^t~&3e*Y(}y({{c_w5XQAtT2*mNoub)S-R< zF8rTW_QPY=-l=8zWw~O(!N?V=$VPwpvTGl;XpJleQoQu7JdY`-J)FI6qmixx*ng*7OmQ~wW4`yTlmzvso}<^ z&HMy0*wWD+Uemh1EyGF*!iSu~`1tYq_J;6y#PPzLn%l!|9W5=*t?k1-&qRC2i-zwH zh4BsEFuw;JUbm)kBdq3aJ$0*RViP|QTbp}o-DnB+{MXdC;hU`ZJoj;9F_gd4IAI`u z9Klb)9yi?0HSPnlsEOrt15vl(mNj*C_zlMK75K5{uF-wf6sATDwVhCptPu0{^b^;K zlnhESHpcNPjhQn)6FFh9_KU=Db{PG63Hy(~zo4f14KGBK4s)C!^gOTE@fK>CwC0ym-El86k3WF)U zcE?rzB8*^oJD`bDC@l*JdT$HbnCv*~XznG>weaHL2&9`5L^S3kHE8Uoa`CaW8>#m? z=7PcgACptq+bmGU^?GoOi8atX;RamWJCxan?m={CWpb&y zlpzgp_sBdO|5Jw2-N$m?LfR?An6cC#O{50-m6tThZ!opjHV9b_bsMeJ-n$WseC|Vb zQv1}w-}w;#Qu|RQBb3&iFIr@tiFDF>?t;_G5gvXgL#+nY7;g0!&6;s5f6j z$-EQ)LZ_HAJObTNUnxTtdWse5N0m_KB>tDOJKF6F}-Je0QQ7;(^|MYB8-zn zag>wJWi^B8bKp+txo~z7Zg)Gc({LFRF9}M^4^zA5AIQDR8R>b*NM`yqaQ8{y2>(+o=PyuCzk-Qm z*y*48GMM=;BYc`U7teiye@K8>Ayxy+Y|%cgL~Sdj={b zeJ_75+IuWgO}~~2^k!qH-$=7opH^sOrC-S_4P)*q=Gw}_AZw+6hN++r{(@$1qD6;G z*QMXbg*s2U1tsWvGmAUM-U1ICRrZ+Oh}^FU4(6nPi)D{x5RQ%ufdM=^1|o)K=iwih zA-C-PUq{Fw_J2E%PHuxSN?8ZG<83j!GQg|0)F6+Nfj@%No{WE1U%K|c=S7{&s6*i? zQSb9b9r`d$&uCyQY&qEN{RJqINpl7x@&&oUSd_#1nu+NA(XJd~FA1c745K%p$o2v^ zKGU%GbEQoae*xpOuv~P>IvkIW?7oHSvsc2~f(gX>B4Q20c^95^9)xF@AwP)6LaKJ& z5W6Z6LJg$`d87`!k!E=7)e2*`_xDACjF}kCJPXg^i;)W!fSIrxv!Ibv2d@m&+6aEG zh)b?W;HjG+4TCp++C}B(k+wB7z-HX&mT@+`?EOFYlG(^)<{{274l(w|6>#2%eb85! zvrWxV{~N^97DMEkmnk6LMQ4(~fcbs!LPHu~6wq~`kS$j3DAhXbYVoQpQLAH!U7hkr zyK2Iz*5E>fzG>$4s4NY$y4`|6WnI+fmFszeyBsbl8kfK{MH|dFf!J(PEM6WY zHpYJZCXe;Z7*fvztTbj}XgWHUeH+u{)&q&z`=7%YVe)nx^L7tYm%QChy*DXtMO^z1 z9zpEG!x}M)+{vun4asEuE@u2=ijwiqGjtfNjpkh4zK5$#Plq^$t!>{+OM!hgqq%6L zeIL(YTs~I{$=qoBar|K+$HVIc?e`@scLB8i2rVvj2`xJxRRP;pZXE)++SW=F5Wrot z-1FeaBbi@uqTUw#uVToky$Io2T)7Xx!9}?EAt%q?X3=X$N3O=9AGk0WI3KDnLY3=t zJ*g>d6PxFWZU<~0K{yMbmH#|?nEj4h`CFy(@55W+rt;s}4aJ|J8U~#Why4!gh%=i( zKVm<5m-YK!6tAO|cNzK%h{G_SwCtk{twq3~Ptod8hVr~Owza<9vfpEpcR(D|!gl;4 z8zZo9uBrX^S^GTWjy}Mq`4cnL0kzRwSl9l5C$5Jejv0wE+JELbD6ntA7=Gc{KE`AM z`^rc2`^xr*2N9F2pGq@60l_rmxK~gnR9o&CW*N2d*NhW3=U=VdTcO1@&icXts$W_N z?OAT+K7xlJneg1J zw%EQ)&<_}?1OKa?eO4;8Eu?RanhI^^d@!e{9E_PU7CtpdpVZ(TaLWP5V#@)SZKZLg z%JGk~YF60|P~c`pgRMAxBXW*eW$%V>f7ESMT78vGvr{Nbv!7|RW!ZzH((Y$U`1z0{ z((q^5Jka(tTw4AtRJ3J%6SA}d7m3sngXa;J0a;IRl1B_DV?Clt2^d96kY%MYpW`ow zF?(ZD3C47DOR!N&z*SnKGJ z$#EW9&*b7AgA+%Q`m~o8b++Kw65aL>qatL8?%RLOw zMeux1ZSk;Kf}?_m5Qo)j9!@-hc$_{1WjTUggTp<7V8yi9gbKK9t_0#v8mo{G(^}t@ z+N(f)L^>k4SB=rz}T|kuQZTvr3(&VM2=B$Sln+$HxFUBeCTnwodb|^AdPM61W2f zPBhP>g~FepO}q7LhMl6#$Ore-Jw-2I9ORyQP0>VTpL^>5qQ7Cp&c08(N(z@eT;wH)4x?T9zonQ8;ZCnIrsEG72SZi+|!>fdJLmA_w-jL ztp>QKX9XrzBRco=XkZdohv%MN7nsDAz`3W-5BMM9FYVXUPX0MyU(3m!nt6I=1%C7! zjQ=(;r8|Bxh~f|oN*iSnp`cBf5p0O*xrjX&dKtap@A_tT^K4E=SQf;PNrGZG+pg%% z$l1eTG76vWLEFjpo9!WH(L6oj2+@A8em?uX$FJy}U;*V(WsE&x?~z)RT4wJ064r2hbvK12hy2FDwwB;*>Dga$fc8yZmJqJ}B?suDEyVDfT;i1uVe&&v+u{Q5 zp2;dPX&SqVa5Gbt5cB_3VSQaH-p^To?uIdk6-~Gbi4~2D11MAxu0mpcV(^ASHQ_2$ zCsa7w6Mcm!5N8chXncuxj4#2f*RK6%j3_K2jD=;yRO3sOigOuJCe9_qW#U{$d>XrB zoogSU!%ZZypt+)5MVLgE5+%l$C>7^YV!k-52$T7x{>&%VPgHcP31fE^G1>SMrQ%#g z%oJxeVeGE*+fA%ih6JpAqR0{jEdKm5zG-;SwSaIoqHMeI|0(RYwaj>69s|d6@v0eJL0S+Oj4CE!ugu`RuY}!tj2$D8wwY? z3Q>Y0VVELHy-q>bOcOxxa=UA987W4V5bSeQFoViO6F`)B0d%pm;2#27H37s0 zUI1OYOaQ^UME@sDoh%{TtR?obUZTt8l&wlB#&W{dP3$+LMYozTN6=Ej95&Sib8cHp ziP_?;CYWvb5*Ha?!enwO!DAEoB}^Wc`ty+3#~8vs=4vGOF%1v;!h^8uZBN4$u<{O& z&tb<8>OVd}2d};vK$c>c06N&L3?O;u(|4x274g1=9UX)?D9&o)0pm+NDb7_)<89+4 zj)}99_(+`9L=UlF$@>Nc#z{;OXSJIdqy|;l#^FCpf;`dw$@EYbA+d*k1~E-0SJH?n z<4U+>%f|nQu(JwCa}ZS$CekuSdKo+NMVR=@;PSQ%xDZOX19D};fE*HqC4{Sx*iBPK zp^9)768ol^1XUBRLSo11gAjHck{Zb!N5g}@@Pv-@?@)$ZlneDtM8sJ`Of|klvGFBJ z#aT(*FU}f*cQF!s2RvovH;hK3;52rZ5tFgQmoRph5oQcnLi}13mJzPq#8w?C3RQ%$ zdj`SL5a)No*gb=oWqb)^_YA+?#Lh5QbgKztcR7(~dr~`TUsPM z?*O?OyNnieJfi{Ri*5iNFKGbTiQPAh%!XJcUX?_RIID@3#+TSA&Xr7KuW=Il#aT(* zBF<{!KI3~Bc+xnDAB(fv&5UmtVeNckFKLnJHOzpo!*oLI+F{OyF9!^A9d@Kem@+J- z3C;}QOLU5JDgJv~ceoHr^c5#7!`sZExP&mF%e){svaqB35GFLiGOu-DnFwJ|%=&fk z31FwcyA4zaZE?#nkP8JmX@y%@{+kmYoorNYgAHV8r<12vZmz#e9wFS^bX>c}*IZEg z!~Yfe;HnP+>vyQ4E{ims;I|LfiI-i9uI*^tSQo|509zV2*0)C2v~C*T)ZA1*zJATx z#_>h5!tn)p`4i8bAjq3iFfqEIv8iM0#KJ_)Xk%0D#*VuB=%zJT(YC4neEwOpSy%?WYvmYKW_)J%o{ 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 Fe*uzPlCl5* diff --git a/components/security/mbedtls/lib/linux/libmbedtls.a.lwip b/components/security/mbedtls/lib/linux/libmbedtls.a.lwip deleted file mode 100644 index b602d48500cc653956c356aeb9e8d992c8b782fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 579622 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

=+zop-zMg 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 QtH}Fs(t{LvA5Hqd0EJulVE_OC diff --git a/components/security/mbedtls/lib/xtensa/libmbedtls.a.dbg b/components/security/mbedtls/lib/xtensa/libmbedtls.a.dbg deleted file mode 100644 index f15361882cc8d95c66afc95d4c2d4acda458a8a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1003350 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 z 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 Wv&Z8Snm)ze@-olk`=IL7-v0r{DS<8k diff --git a/components/security/mbedtls/src/aes.c b/components/security/mbedtls/src/aes.c deleted file mode 100644 index 8823a54a..00000000 --- a/components/security/mbedtls/src/aes.c +++ /dev/null @@ -1,1494 +0,0 @@ -/* - * FIPS-197 compliant AES implementation - * - * 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) - */ -/* - * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. - * - * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf - * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_AES_C) - -#include - -#include "mbedtls/aes.h" -#if defined(MBEDTLS_PADLOCK_C) -#include "mbedtls/padlock.h" -#endif -#if defined(MBEDTLS_AESNI_C) -#include "mbedtls/aesni.h" -#endif - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_AES_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -#if defined(MBEDTLS_PADLOCK_C) && \ - ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) -static int aes_padlock_ace = -1; -#endif - -#if defined(MBEDTLS_AES_ROM_TABLES) -/* - * Forward S-box - */ -static const unsigned char FSb[256] = -{ - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, - 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, - 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, - 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, - 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, - 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, - 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, - 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, - 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 -}; - -/* - * Forward tables - */ -#define FT \ -\ - V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ - V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ - V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ - V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ - V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ - V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ - V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ - V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ - V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ - V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ - V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ - V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ - V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ - V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ - V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ - V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ - V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ - V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ - V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ - V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ - V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ - V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ - V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ - V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ - V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ - V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ - V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ - V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ - V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ - V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ - V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ - V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ - V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ - V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ - V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ - V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ - V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ - V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ - V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ - V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ - V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ - V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ - V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ - V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ - V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ - V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ - V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ - V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ - V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ - V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ - V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ - V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ - V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ - V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ - V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ - V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ - V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ - V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ - V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ - V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ - V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ - V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ - V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ - V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) - -#define V(a,b,c,d) 0x##a##b##c##d -static const uint32_t FT0[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const uint32_t FT1[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const uint32_t FT2[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const uint32_t FT3[256] = { FT }; -#undef V - -#undef FT - -/* - * Reverse S-box - */ -static const unsigned char RSb[256] = -{ - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, - 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, - 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, - 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, - 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, - 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, - 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, - 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, - 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, - 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, - 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, - 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D -}; - -/* - * Reverse tables - */ -#define RT \ -\ - V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ - V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ - V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ - V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ - V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ - V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ - V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ - V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ - V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ - V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ - V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ - V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ - V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ - V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ - V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ - V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ - V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ - V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ - V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ - V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ - V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ - V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ - V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ - V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ - V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ - V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ - V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ - V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ - V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ - V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ - V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ - V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ - V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ - V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ - V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ - V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ - V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ - V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ - V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ - V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ - V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ - V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ - V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ - V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ - V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ - V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ - V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ - V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ - V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ - V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ - V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ - V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ - V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ - V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ - V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ - V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ - V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ - V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ - V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ - V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ - V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ - V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ - V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ - V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) - -#define V(a,b,c,d) 0x##a##b##c##d -static const uint32_t RT0[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const uint32_t RT1[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const uint32_t RT2[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const uint32_t RT3[256] = { RT }; -#undef V - -#undef RT - -/* - * Round constants - */ -static const uint32_t RCON[10] = -{ - 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x0000001B, 0x00000036 -}; - -#else /* MBEDTLS_AES_ROM_TABLES */ - -/* - * Forward S-box & tables - */ -static unsigned char FSb[256]; -static uint32_t FT0[256]; -static uint32_t FT1[256]; -static uint32_t FT2[256]; -static uint32_t FT3[256]; - -/* - * Reverse S-box & tables - */ -static unsigned char RSb[256]; -static uint32_t RT0[256]; -static uint32_t RT1[256]; -static uint32_t RT2[256]; -static uint32_t RT3[256]; - -/* - * Round constants - */ -static uint32_t RCON[10]; - -/* - * Tables generation code - */ -#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) -#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) -#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) - -static int aes_init_done = 0; - -static void aes_gen_tables( void ) -{ - int i, x, y, z; - int pow[256]; - int log[256]; - - /* - * compute pow and log tables over GF(2^8) - */ - for( i = 0, x = 1; i < 256; i++ ) - { - pow[i] = x; - log[x] = i; - x = ( x ^ XTIME( x ) ) & 0xFF; - } - - /* - * calculate the round constants - */ - for( i = 0, x = 1; i < 10; i++ ) - { - RCON[i] = (uint32_t) x; - x = XTIME( x ) & 0xFF; - } - - /* - * generate the forward and reverse S-boxes - */ - FSb[0x00] = 0x63; - RSb[0x63] = 0x00; - - for( i = 1; i < 256; i++ ) - { - x = pow[255 - log[i]]; - - y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y ^ 0x63; - - FSb[i] = (unsigned char) x; - RSb[x] = (unsigned char) i; - } - - /* - * generate the forward and reverse tables - */ - for( i = 0; i < 256; i++ ) - { - x = FSb[i]; - y = XTIME( x ) & 0xFF; - z = ( y ^ x ) & 0xFF; - - FT0[i] = ( (uint32_t) y ) ^ - ( (uint32_t) x << 8 ) ^ - ( (uint32_t) x << 16 ) ^ - ( (uint32_t) z << 24 ); - - FT1[i] = ROTL8( FT0[i] ); - FT2[i] = ROTL8( FT1[i] ); - FT3[i] = ROTL8( FT2[i] ); - - x = RSb[i]; - - RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ - ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ - ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ - ( (uint32_t) MUL( 0x0B, x ) << 24 ); - - RT1[i] = ROTL8( RT0[i] ); - RT2[i] = ROTL8( RT1[i] ); - RT3[i] = ROTL8( RT2[i] ); - } -} - -#endif /* MBEDTLS_AES_ROM_TABLES */ - -void mbedtls_aes_init( mbedtls_aes_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_aes_context ) ); -} - -void mbedtls_aes_free( mbedtls_aes_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); -} - -/* - * AES key schedule (encryption) - */ -#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) -int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - unsigned int i; - uint32_t *RK; - -#if !defined(MBEDTLS_AES_ROM_TABLES) - if( aes_init_done == 0 ) - { - aes_gen_tables(); - aes_init_done = 1; - - } -#endif - - switch( keybits ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); - } - -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) - if( aes_padlock_ace == -1 ) - aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); - - if( aes_padlock_ace ) - ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); - else -#endif - ctx->rk = RK = ctx->buf; - -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) - return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); -#endif - - for( i = 0; i < ( keybits >> 5 ); i++ ) - { - GET_UINT32_LE( RK[i], key, i << 2 ); - } - - switch( ctx->nr ) - { - case 10: - - for( i = 0; i < 10; i++, RK += 4 ) - { - RK[4] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; - } - break; - - case 12: - - for( i = 0; i < 8; i++, RK += 6 ) - { - RK[6] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); - - RK[7] = RK[1] ^ RK[6]; - RK[8] = RK[2] ^ RK[7]; - RK[9] = RK[3] ^ RK[8]; - RK[10] = RK[4] ^ RK[9]; - RK[11] = RK[5] ^ RK[10]; - } - break; - - case 14: - - for( i = 0; i < 7; i++, RK += 8 ) - { - RK[8] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); - - RK[9] = RK[1] ^ RK[8]; - RK[10] = RK[2] ^ RK[9]; - RK[11] = RK[3] ^ RK[10]; - - RK[12] = RK[4] ^ - ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); - - RK[13] = RK[5] ^ RK[12]; - RK[14] = RK[6] ^ RK[13]; - RK[15] = RK[7] ^ RK[14]; - } - break; - } - - return( 0 ); -} -#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ - -/* - * AES key schedule (decryption) - */ -#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) -int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - int i, j, ret; - mbedtls_aes_context cty; - uint32_t *RK; - uint32_t *SK; - - mbedtls_aes_init( &cty ); - -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) - if( aes_padlock_ace == -1 ) - aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); - - if( aes_padlock_ace ) - ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); - else -#endif - ctx->rk = RK = ctx->buf; - - /* Also checks keybits */ - if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) - goto exit; - - ctx->nr = cty.nr; - -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) - { - mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, - (const unsigned char *) cty.rk, ctx->nr ); - goto exit; - } -#endif - - SK = cty.rk + cty.nr * 4; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) - { - for( j = 0; j < 4; j++, SK++ ) - { - *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ - RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ - RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ - RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; - } - } - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - -exit: - mbedtls_aes_free( &cty ); - - return( ret ); -} -#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ - -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ - FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ - FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y0 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ - FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ - FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y2 >> 24 ) & 0xFF ]; \ -} - -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ - RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ - RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y2 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ - RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ - RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y0 >> 24 ) & 0xFF ]; \ -} - -/* - * AES-ECB block encryption - */ -#if !defined(MBEDTLS_AES_ENCRYPT_ALT) -void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) -{ - int i; - uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - - RK = ctx->rk; - - GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; - GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; - GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; - GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; - - for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) - { - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - - PUT_UINT32_LE( X0, output, 0 ); - PUT_UINT32_LE( X1, output, 4 ); - PUT_UINT32_LE( X2, output, 8 ); - PUT_UINT32_LE( X3, output, 12 ); -} -#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ - -/* - * AES-ECB block decryption - */ -#if !defined(MBEDTLS_AES_DECRYPT_ALT) -void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) -{ - int i; - uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - - RK = ctx->rk; - - GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; - GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; - GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; - GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; - - for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) - { - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - - PUT_UINT32_LE( X0, output, 0 ); - PUT_UINT32_LE( X1, output, 4 ); - PUT_UINT32_LE( X2, output, 8 ); - PUT_UINT32_LE( X3, output, 12 ); -} -#endif /* !MBEDTLS_AES_DECRYPT_ALT */ - -#if !defined(MBEDTLS_AES_ALT) -/* - * AES-ECB block encryption/decryption - */ -int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) - return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); -#endif - -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) - if( aes_padlock_ace ) - { - if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - if( mode == MBEDTLS_AES_ENCRYPT ) - mbedtls_aes_encrypt( ctx, input, output ); - else - mbedtls_aes_decrypt( ctx, input, output ); - - return( 0 ); -} -#endif /* !MBEDTLS_AES_ALT */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * AES-CBC buffer encryption/decryption - */ -int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[16]; - - if( length % 16 ) - return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); - -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) - if( aes_padlock_ace ) - { - if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - if( mode == MBEDTLS_AES_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 16 ); - mbedtls_aes_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_aes_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * AES-CFB128 buffer encryption/decryption - */ -int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == MBEDTLS_AES_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = ( n + 1 ) & 0x0F; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = ( n + 1 ) & 0x0F; - } - } - - *iv_off = n; - - return( 0 ); -} - -/* - * AES-CFB8 buffer encryption/decryption - */ -int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - unsigned char c; - unsigned char ov[17]; - - while( length-- ) - { - memcpy( ov, iv, 16 ); - mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); - - if( mode == MBEDTLS_AES_DECRYPT ) - ov[16] = *input; - - c = *output++ = (unsigned char)( iv[0] ^ *input++ ); - - if( mode == MBEDTLS_AES_ENCRYPT ) - ov[16] = c; - - memcpy( iv, ov + 1, 16 ); - } - - return( 0 ); -} -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * AES-CTR buffer encryption/decryption - */ -int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); - - for( i = 16; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = ( n + 1 ) & 0x0F; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#endif /* !MBEDTLS_AES_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * AES test vectors from: - * - * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip - */ -static const unsigned char aes_test_ecb_dec[3][16] = -{ - { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, - 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, - { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, - 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, - { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, - 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } -}; - -static const unsigned char aes_test_ecb_enc[3][16] = -{ - { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, - 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, - { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, - 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, - { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, - 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const unsigned char aes_test_cbc_dec[3][16] = -{ - { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, - 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, - { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, - 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, - { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, - 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } -}; - -static const unsigned char aes_test_cbc_enc[3][16] = -{ - { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, - 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, - { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, - 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, - { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, - 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * AES-CFB128 test vectors from: - * - * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - */ -static const unsigned char aes_test_cfb128_key[3][32] = -{ - { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, - 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, - { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, - 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, - 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } -}; - -static const unsigned char aes_test_cfb128_iv[16] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F -}; - -static const unsigned char aes_test_cfb128_pt[64] = -{ - 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, - 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, - 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, - 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, - 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, - 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 -}; - -static const unsigned char aes_test_cfb128_ct[3][64] = -{ - { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, - 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, - 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, - 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, - 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, - 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, - 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, - 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, - { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, - 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, - 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, - 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, - 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, - 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, - 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, - 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, - { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, - 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, - 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, - 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, - 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, - 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, - 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, - 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * AES-CTR test vectors from: - * - * http://www.faqs.org/rfcs/rfc3686.html - */ - -static const unsigned char aes_test_ctr_key[3][16] = -{ - { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, - 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, - { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, - 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, - { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, - 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } -}; - -static const unsigned char aes_test_ctr_nonce_counter[3][16] = -{ - { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, - 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, - 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } -}; - -static const unsigned char aes_test_ctr_pt[3][48] = -{ - { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, - 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23 } -}; - -static const unsigned char aes_test_ctr_ct[3][48] = -{ - { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, - 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, - { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, - 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, - 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, - 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, - { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, - 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, - 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, - 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, - 0x25, 0xB2, 0x07, 0x2F } -}; - -static const int aes_test_ctr_len[3] = - { 16, 32, 36 }; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -/* - * Checkup routine - */ -int mbedtls_aes_self_test( int verbose ) -{ - int ret = 0, i, j, u, v; - unsigned char key[32]; - unsigned char buf[64]; -#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) - unsigned char iv[16]; -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - unsigned char prv[16]; -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) - size_t offset; -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - int len; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; -#endif - mbedtls_aes_context ctx; - - memset( key, 0, 32 ); - mbedtls_aes_init( &ctx ); - - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); - - memset( buf, 0, 16 ); - - if( v == MBEDTLS_AES_DECRYPT ) - { - mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " AES-CBC-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); - - memset( iv , 0, 16 ); - memset( prv, 0, 16 ); - memset( buf, 0, 16 ); - - if( v == MBEDTLS_AES_DECRYPT ) - { - mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[16]; - - mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - memcpy( tmp, prv, 16 ); - memcpy( prv, buf, 16 ); - memcpy( buf, tmp, 16 ); - } - - if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) - /* - * CFB128 mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, aes_test_cfb128_iv, 16 ); - memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); - - offset = 0; - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - if( v == MBEDTLS_AES_DECRYPT ) - { - memcpy( buf, aes_test_cfb128_ct[u], 64 ); - mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - memcpy( buf, aes_test_cfb128_pt, 64 ); - mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) - /* - * CTR mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " AES-CTR-128 (%s): ", - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); - memcpy( key, aes_test_ctr_key[u], 16 ); - - offset = 0; - mbedtls_aes_setkey_enc( &ctx, key, 128 ); - - if( v == MBEDTLS_AES_DECRYPT ) - { - len = aes_test_ctr_len[u]; - memcpy( buf, aes_test_ctr_ct[u], len ); - - mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - len = aes_test_ctr_len[u]; - memcpy( buf, aes_test_ctr_pt[u], len ); - - mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - - ret = 0; - -exit: - mbedtls_aes_free( &ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_AES_C */ diff --git a/components/security/mbedtls/src/aesni.c b/components/security/mbedtls/src/aesni.c deleted file mode 100644 index 1ca3c3ef..00000000 --- a/components/security/mbedtls/src/aesni.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * AES-NI support 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) - */ - -/* - * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set - * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_AESNI_C) - -#include "mbedtls/aesni.h" - -#include - -#ifndef asm -#define asm __asm -#endif - -#if defined(MBEDTLS_HAVE_X86_64) - -/* - * AES-NI support detection routine - */ -int mbedtls_aesni_has_support( unsigned int what ) -{ - static int done = 0; - static unsigned int c = 0; - - if( ! done ) - { - asm( "movl $1, %%eax \n\t" - "cpuid \n\t" - : "=c" (c) - : - : "eax", "ebx", "edx" ); - done = 1; - } - - return( ( c & what ) != 0 ); -} - -/* - * Binutils needs to be at least 2.19 to support AES-NI instructions. - * Unfortunately, a lot of users have a lower version now (2014-04). - * Emit bytecode directly in order to support "old" version of gas. - * - * Opcodes from the Intel architecture reference manual, vol. 3. - * We always use registers, so we don't need prefixes for memory operands. - * Operand macros are in gas order (src, dst) as opposed to Intel order - * (dst, src) in order to blend better into the surrounding assembly code. - */ -#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," -#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," -#define AESENC ".byte 0x66,0x0F,0x38,0xDC," -#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," -#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," -#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," -#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," - -#define xmm0_xmm0 "0xC0" -#define xmm0_xmm1 "0xC8" -#define xmm0_xmm2 "0xD0" -#define xmm0_xmm3 "0xD8" -#define xmm0_xmm4 "0xE0" -#define xmm1_xmm0 "0xC1" -#define xmm1_xmm2 "0xD1" - -/* - * AES-NI AES-ECB block en(de)cryption - */ -int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - asm( "movdqu (%3), %%xmm0 \n\t" // load input - "movdqu (%1), %%xmm1 \n\t" // load round key 0 - "pxor %%xmm1, %%xmm0 \n\t" // round 0 - "add $16, %1 \n\t" // point to next round key - "subl $1, %0 \n\t" // normal rounds = nr - 1 - "test %2, %2 \n\t" // mode? - "jz 2f \n\t" // 0 = decrypt - - "1: \n\t" // encryption loop - "movdqu (%1), %%xmm1 \n\t" // load round key - AESENC xmm1_xmm0 "\n\t" // do round - "add $16, %1 \n\t" // point to next round key - "subl $1, %0 \n\t" // loop - "jnz 1b \n\t" - "movdqu (%1), %%xmm1 \n\t" // load round key - AESENCLAST xmm1_xmm0 "\n\t" // last round - "jmp 3f \n\t" - - "2: \n\t" // decryption loop - "movdqu (%1), %%xmm1 \n\t" - AESDEC xmm1_xmm0 "\n\t" // do round - "add $16, %1 \n\t" - "subl $1, %0 \n\t" - "jnz 2b \n\t" - "movdqu (%1), %%xmm1 \n\t" // load round key - AESDECLAST xmm1_xmm0 "\n\t" // last round - - "3: \n\t" - "movdqu %%xmm0, (%4) \n\t" // export output - : - : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) - : "memory", "cc", "xmm0", "xmm1" ); - - - return( 0 ); -} - -/* - * GCM multiplication: c = a times b in GF(2^128) - * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. - */ -void mbedtls_aesni_gcm_mult( unsigned char c[16], - const unsigned char a[16], - const unsigned char b[16] ) -{ - unsigned char aa[16], bb[16], cc[16]; - size_t i; - - /* The inputs are in big-endian order, so byte-reverse them */ - for( i = 0; i < 16; i++ ) - { - aa[i] = a[15 - i]; - bb[i] = b[15 - i]; - } - - asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 - "movdqu (%1), %%xmm1 \n\t" // b1:b0 - - /* - * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 - * using [CLMUL-WP] algorithm 1 (p. 13). - */ - "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 - "movdqa %%xmm1, %%xmm3 \n\t" // same - "movdqa %%xmm1, %%xmm4 \n\t" // same - PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 - PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 - PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 - PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 - "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 - "movdqa %%xmm4, %%xmm3 \n\t" // same - "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 - "pslldq $8, %%xmm3 \n\t" // e0+f0:0 - "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 - "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 - - /* - * Now shift the result one bit to the left, - * taking advantage of [CLMUL-WP] eq 27 (p. 20) - */ - "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 - "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 - "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 - "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 - "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 - "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 - "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 - "pslldq $8, %%xmm3 \n\t" // r0>>63:0 - "pslldq $8, %%xmm4 \n\t" // r2>>63:0 - "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 - "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 - "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 - "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 - - /* - * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 - * using [CLMUL-WP] algorithm 5 (p. 20). - * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). - */ - /* Step 2 (1) */ - "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 - "movdqa %%xmm1, %%xmm4 \n\t" // same - "movdqa %%xmm1, %%xmm5 \n\t" // same - "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a - "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b - "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c - - /* Step 2 (2) */ - "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b - "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c - "pslldq $8, %%xmm3 \n\t" // a+b+c:0 - "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 - - /* Steps 3 and 4 */ - "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 - "movdqa %%xmm1,%%xmm4 \n\t" // same - "movdqa %%xmm1,%%xmm5 \n\t" // same - "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' - "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' - "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' - "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' - "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' - // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing - // bits carried from d. Now get those\t bits back in. - "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 - "movdqa %%xmm1,%%xmm4 \n\t" // same - "movdqa %%xmm1,%%xmm5 \n\t" // same - "psllq $63, %%xmm3 \n\t" // d<<63:stuff - "psllq $62, %%xmm4 \n\t" // d<<62:stuff - "psllq $57, %%xmm5 \n\t" // d<<57:stuff - "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff - "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff - "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d - "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 - "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 - "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 - - "movdqu %%xmm0, (%2) \n\t" // done - : - : "r" (aa), "r" (bb), "r" (cc) - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); - - /* Now byte-reverse the outputs */ - for( i = 0; i < 16; i++ ) - c[i] = cc[15 - i]; - - return; -} - -/* - * Compute decryption round keys from encryption round keys - */ -void mbedtls_aesni_inverse_key( unsigned char *invkey, - const unsigned char *fwdkey, int nr ) -{ - unsigned char *ik = invkey; - const unsigned char *fk = fwdkey + 16 * nr; - - memcpy( ik, fk, 16 ); - - for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) - asm( "movdqu (%0), %%xmm0 \n\t" - AESIMC xmm0_xmm0 "\n\t" - "movdqu %%xmm0, (%1) \n\t" - : - : "r" (fk), "r" (ik) - : "memory", "xmm0" ); - - memcpy( ik, fk, 16 ); -} - -/* - * Key expansion, 128-bit case - */ -static void aesni_setkey_enc_128( unsigned char *rk, - const unsigned char *key ) -{ - asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key - "movdqu %%xmm0, (%0) \n\t" // as round key 0 - "jmp 2f \n\t" // skip auxiliary routine - - /* - * Finish generating the next round key. - * - * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff - * with X = rot( sub( r3 ) ) ^ RCON. - * - * On exit, xmm0 is r7:r6:r5:r4 - * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 - * and those are written to the round key buffer. - */ - "1: \n\t" - "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X - "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 - "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 - "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 - "pslldq $4, %%xmm0 \n\t" // etc - "pxor %%xmm0, %%xmm1 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! - "add $16, %0 \n\t" // point to next round key - "movdqu %%xmm0, (%0) \n\t" // write it - "ret \n\t" - - /* Main "loop" */ - "2: \n\t" - AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" - : - : "r" (rk), "r" (key) - : "memory", "cc", "0" ); -} - -/* - * Key expansion, 192-bit case - */ -static void aesni_setkey_enc_192( unsigned char *rk, - const unsigned char *key ) -{ - asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key - "movdqu %%xmm0, (%0) \n\t" - "add $16, %0 \n\t" - "movq 16(%1), %%xmm1 \n\t" - "movq %%xmm1, (%0) \n\t" - "add $8, %0 \n\t" - "jmp 2f \n\t" // skip auxiliary routine - - /* - * Finish generating the next 6 quarter-keys. - * - * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 - * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. - * - * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 - * and those are written to the round key buffer. - */ - "1: \n\t" - "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X - "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 - "pslldq $4, %%xmm0 \n\t" // etc - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 - "movdqu %%xmm0, (%0) \n\t" - "add $16, %0 \n\t" - "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 - "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 - "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 - "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 - "movq %%xmm1, (%0) \n\t" - "add $8, %0 \n\t" - "ret \n\t" - - "2: \n\t" - AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" - - : - : "r" (rk), "r" (key) - : "memory", "cc", "0" ); -} - -/* - * Key expansion, 256-bit case - */ -static void aesni_setkey_enc_256( unsigned char *rk, - const unsigned char *key ) -{ - asm( "movdqu (%1), %%xmm0 \n\t" - "movdqu %%xmm0, (%0) \n\t" - "add $16, %0 \n\t" - "movdqu 16(%1), %%xmm1 \n\t" - "movdqu %%xmm1, (%0) \n\t" - "jmp 2f \n\t" // skip auxiliary routine - - /* - * Finish generating the next two round keys. - * - * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and - * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON - * - * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 - * and those have been written to the output buffer. - */ - "1: \n\t" - "pshufd $0xff, %%xmm2, %%xmm2 \n\t" - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm2, %%xmm0 \n\t" - "add $16, %0 \n\t" - "movdqu %%xmm0, (%0) \n\t" - - /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) - * and proceed to generate next round key from there */ - AESKEYGENA xmm0_xmm2 ",0x00 \n\t" - "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm2, %%xmm1 \n\t" - "add $16, %0 \n\t" - "movdqu %%xmm1, (%0) \n\t" - "ret \n\t" - - /* - * Main "loop" - Generating one more key than necessary, - * see definition of mbedtls_aes_context.buf - */ - "2: \n\t" - AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" - : - : "r" (rk), "r" (key) - : "memory", "cc", "0" ); -} - -/* - * Key expansion, wrapper - */ -int mbedtls_aesni_setkey_enc( unsigned char *rk, - const unsigned char *key, - size_t bits ) -{ - switch( bits ) - { - case 128: aesni_setkey_enc_128( rk, key ); break; - case 192: aesni_setkey_enc_192( rk, key ); break; - case 256: aesni_setkey_enc_256( rk, key ); break; - default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); - } - - return( 0 ); -} - -#endif /* MBEDTLS_HAVE_X86_64 */ - -#endif /* MBEDTLS_AESNI_C */ diff --git a/components/security/mbedtls/src/arc4.c b/components/security/mbedtls/src/arc4.c deleted file mode 100644 index 05b33d3f..00000000 --- a/components/security/mbedtls/src/arc4.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * An implementation of the ARCFOUR algorithm - * - * 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) - */ -/* - * The ARCFOUR algorithm was publicly disclosed on 94/09. - * - * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ARC4_C) - -#include "mbedtls/arc4.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_ARC4_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); -} - -void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); -} - -/* - * ARC4 key schedule - */ -void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, - unsigned int keylen ) -{ - int i, j, a; - unsigned int k; - unsigned char *m; - - ctx->x = 0; - ctx->y = 0; - m = ctx->m; - - for( i = 0; i < 256; i++ ) - m[i] = (unsigned char) i; - - j = k = 0; - - for( i = 0; i < 256; i++, k++ ) - { - if( k >= keylen ) k = 0; - - a = m[i]; - j = ( j + a + key[k] ) & 0xFF; - m[i] = m[j]; - m[j] = (unsigned char) a; - } -} - -/* - * ARC4 cipher function - */ -int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, - unsigned char *output ) -{ - int x, y, a, b; - size_t i; - unsigned char *m; - - x = ctx->x; - y = ctx->y; - m = ctx->m; - - for( i = 0; i < length; i++ ) - { - x = ( x + 1 ) & 0xFF; a = m[x]; - y = ( y + a ) & 0xFF; b = m[y]; - - m[x] = (unsigned char) b; - m[y] = (unsigned char) a; - - output[i] = (unsigned char) - ( input[i] ^ m[(unsigned char)( a + b )] ); - } - - ctx->x = x; - ctx->y = y; - - return( 0 ); -} - -#endif /* !MBEDTLS_ARC4_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: - * - * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 - */ -static const unsigned char arc4_test_key[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char arc4_test_pt[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char arc4_test_ct[3][8] = -{ - { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, - { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, - { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } -}; - -/* - * Checkup routine - */ -int mbedtls_arc4_self_test( int verbose ) -{ - int i, ret = 0; - unsigned char ibuf[8]; - unsigned char obuf[8]; - mbedtls_arc4_context ctx; - - mbedtls_arc4_init( &ctx ); - - for( i = 0; i < 3; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " ARC4 test #%d: ", i + 1 ); - - memcpy( ibuf, arc4_test_pt[i], 8 ); - - mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); - mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); - - if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_arc4_free( &ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_ARC4_C */ diff --git a/components/security/mbedtls/src/asn1parse.c b/components/security/mbedtls/src/asn1parse.c deleted file mode 100644 index 4dd65c03..00000000 --- a/components/security/mbedtls/src/asn1parse.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Generic ASN.1 parsing - * - * 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_ASN1_PARSE_C) - -#include "mbedtls/asn1.h" - -#include - -#if defined(MBEDTLS_BIGNUM_C) -#include "mbedtls/bignum.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * ASN.1 DER decoding routines - */ -int mbedtls_asn1_get_len( unsigned char **p, - const unsigned char *end, - size_t *len ) -{ - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( ( **p & 0x80 ) == 0 ) - *len = *(*p)++; - else - { - switch( **p & 0x7F ) - { - case 1: - if( ( end - *p ) < 2 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - *len = (*p)[1]; - (*p) += 2; - break; - - case 2: - if( ( end - *p ) < 3 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; - (*p) += 3; - break; - - case 3: - if( ( end - *p ) < 4 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (size_t)(*p)[1] << 16 ) | - ( (size_t)(*p)[2] << 8 ) | (*p)[3]; - (*p) += 4; - break; - - case 4: - if( ( end - *p ) < 5 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | - ( (size_t)(*p)[3] << 8 ) | (*p)[4]; - (*p) += 5; - break; - - default: - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - } - } - - if( *len > (size_t) ( end - *p ) ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - return( 0 ); -} - -int mbedtls_asn1_get_tag( unsigned char **p, - const unsigned char *end, - size_t *len, int tag ) -{ - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( **p != tag ) - return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - (*p)++; - - return( mbedtls_asn1_get_len( p, end, len ) ); -} - -int mbedtls_asn1_get_bool( unsigned char **p, - const unsigned char *end, - int *val ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) - return( ret ); - - if( len != 1 ) - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - *val = ( **p != 0 ) ? 1 : 0; - (*p)++; - - return( 0 ); -} - -int mbedtls_asn1_get_int( unsigned char **p, - const unsigned char *end, - int *val ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) - return( ret ); - - if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 ) - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - *val = 0; - - while( len-- > 0 ) - { - *val = ( *val << 8 ) | **p; - (*p)++; - } - - return( 0 ); -} - -#if defined(MBEDTLS_BIGNUM_C) -int mbedtls_asn1_get_mpi( unsigned char **p, - const unsigned char *end, - mbedtls_mpi *X ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) - return( ret ); - - ret = mbedtls_mpi_read_binary( X, *p, len ); - - *p += len; - - return( ret ); -} -#endif /* MBEDTLS_BIGNUM_C */ - -int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, - mbedtls_asn1_bitstring *bs) -{ - int ret; - - /* Certificate type is a single byte bitstring */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) - return( ret ); - - /* Check length, subtract one for actual bit string length */ - if( bs->len < 1 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - bs->len -= 1; - - /* Get number of unused bits, ensure unused bits <= 7 */ - bs->unused_bits = **p; - if( bs->unused_bits > 7 ) - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - (*p)++; - - /* Get actual bitstring */ - bs->p = *p; - *p += bs->len; - - if( *p != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * Get a bit string without unused bits - */ -int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, - size_t *len ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) - return( ret ); - - if( (*len)-- < 2 || *(*p)++ != 0 ) - return( MBEDTLS_ERR_ASN1_INVALID_DATA ); - - return( 0 ); -} - - - -/* - * Parses and splits an ASN.1 "SEQUENCE OF " - */ -int mbedtls_asn1_get_sequence_of( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_sequence *cur, - int tag) -{ - int ret; - size_t len; - mbedtls_asn1_buf *buf; - - /* Get main sequence tag */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - buf = &(cur->buf); - buf->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) - return( ret ); - - buf->p = *p; - *p += buf->len; - - /* Allocate and assign next pointer */ - if( *p < end ) - { - cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, - sizeof( mbedtls_asn1_sequence ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); - - cur = cur->next; - } - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if( *p != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -int mbedtls_asn1_get_alg( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - alg->tag = **p; - end = *p + len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( ret ); - - alg->p = *p; - *p += alg->len; - - if( *p == end ) - { - mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) ); - return( 0 ); - } - - params->tag = **p; - (*p)++; - - if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) - return( ret ); - - params->p = *p; - *p += params->len; - - if( *p != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -int mbedtls_asn1_get_alg_null( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg ) -{ - int ret; - mbedtls_asn1_buf params; - - memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); - - if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) - return( ret ); - - if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) - return( MBEDTLS_ERR_ASN1_INVALID_DATA ); - - return( 0 ); -} - -void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) -{ - if( cur == NULL ) - return; - - mbedtls_free( cur->oid.p ); - mbedtls_free( cur->val.p ); - - mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); -} - -void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) -{ - mbedtls_asn1_named_data *cur; - - while( ( cur = *head ) != NULL ) - { - *head = cur->next; - mbedtls_asn1_free_named_data( cur ); - mbedtls_free( cur ); - } -} - -mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, - const char *oid, size_t len ) -{ - while( list != NULL ) - { - if( list->oid.len == len && - memcmp( list->oid.p, oid, len ) == 0 ) - { - break; - } - - list = list->next; - } - - return( list ); -} - -#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/components/security/mbedtls/src/asn1write.c b/components/security/mbedtls/src/asn1write.c deleted file mode 100644 index 69b61b20..00000000 --- a/components/security/mbedtls/src/asn1write.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * ASN.1 buffer writing functionality - * - * 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_ASN1_WRITE_C) - -#include "mbedtls/asn1write.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) -{ - if( len < 0x80 ) - { - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = (unsigned char) len; - return( 1 ); - } - - if( len <= 0xFF ) - { - if( *p - start < 2 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = (unsigned char) len; - *--(*p) = 0x81; - return( 2 ); - } - - if( len <= 0xFFFF ) - { - if( *p - start < 3 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = ( len ) & 0xFF; - *--(*p) = ( len >> 8 ) & 0xFF; - *--(*p) = 0x82; - return( 3 ); - } - - if( len <= 0xFFFFFF ) - { - if( *p - start < 4 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = ( len ) & 0xFF; - *--(*p) = ( len >> 8 ) & 0xFF; - *--(*p) = ( len >> 16 ) & 0xFF; - *--(*p) = 0x83; - return( 4 ); - } - - if( len <= 0xFFFFFFFF ) - { - if( *p - start < 5 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = ( len ) & 0xFF; - *--(*p) = ( len >> 8 ) & 0xFF; - *--(*p) = ( len >> 16 ) & 0xFF; - *--(*p) = ( len >> 24 ) & 0xFF; - *--(*p) = 0x84; - return( 5 ); - } - - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); -} - -int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) -{ - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = tag; - - return( 1 ); -} - -int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ) -{ - size_t len = 0; - - if( *p < start || (size_t)( *p - start ) < size ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len = size; - (*p) -= len; - memcpy( *p, buf, len ); - - return( (int) len ); -} - -#if defined(MBEDTLS_BIGNUM_C) -int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) -{ - int ret; - size_t len = 0; - - // Write the MPI - // - len = mbedtls_mpi_size( X ); - - if( *p < start || (size_t)( *p - start ) < len ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); - - // DER format assumes 2s complement for numbers, so the leftmost bit - // should be 0 for positive numbers and 1 for negative numbers. - // - if( X->s ==1 && **p & 0x80 ) - { - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0x00; - len += 1; - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); - - ret = (int) len; - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_BIGNUM_C */ - -int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) -{ - int ret; - size_t len = 0; - - // Write NULL - // - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) oid, oid_len ) ); - MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - size_t par_len ) -{ - int ret; - size_t len = 0; - - if( par_len == 0 ) - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); - else - len += par_len; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) -{ - int ret; - size_t len = 0; - - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = (boolean) ? 255 : 0; - len++; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) -{ - int ret; - size_t len = 0; - - // TODO negative values and values larger than 128 - // DER format assumes 2s complement for numbers, so the leftmost bit - // should be 0 for positive numbers and 1 for negative numbers. - // - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len += 1; - *--(*p) = val; - - if( val > 0 && **p & 0x80 ) - { - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0x00; - len += 1; - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) text, text_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) text, text_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t bits ) -{ - int ret; - size_t len = 0, size; - - size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); - - // Calculate byte length - // - if( *p < start || (size_t)( *p - start ) < size + 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len = size + 1; - (*p) -= size; - memcpy( *p, buf, size ); - - // Write unused bits - // - *--(*p) = (unsigned char) (size * 8 - bits); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); - - return( (int) len ); -} - -mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, - const char *oid, size_t oid_len, - const unsigned char *val, - size_t val_len ) -{ - mbedtls_asn1_named_data *cur; - - if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) - { - // Add new entry if not present yet based on OID - // - cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, - sizeof(mbedtls_asn1_named_data) ); - if( cur == NULL ) - return( NULL ); - - cur->oid.len = oid_len; - cur->oid.p = mbedtls_calloc( 1, oid_len ); - if( cur->oid.p == NULL ) - { - mbedtls_free( cur ); - return( NULL ); - } - - memcpy( cur->oid.p, oid, oid_len ); - - cur->val.len = val_len; - cur->val.p = mbedtls_calloc( 1, val_len ); - if( cur->val.p == NULL ) - { - mbedtls_free( cur->oid.p ); - mbedtls_free( cur ); - return( NULL ); - } - - cur->next = *head; - *head = cur; - } - else if( cur->val.len < val_len ) - { - /* - * Enlarge existing value buffer if needed - * Preserve old data until the allocation succeeded, to leave list in - * a consistent state in case allocation fails. - */ - void *p = mbedtls_calloc( 1, val_len ); - if( p == NULL ) - return( NULL ); - - mbedtls_free( cur->val.p ); - cur->val.p = p; - cur->val.len = val_len; - } - - if( val != NULL ) - memcpy( cur->val.p, val, val_len ); - - return( cur ); -} -#endif /* MBEDTLS_ASN1_WRITE_C */ diff --git a/components/security/mbedtls/src/base64.c b/components/security/mbedtls/src/base64.c deleted file mode 100644 index f06b57b3..00000000 --- a/components/security/mbedtls/src/base64.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * RFC 1521 base64 encoding/decoding - * - * 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_BASE64_C) - -#include "mbedtls/base64.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#include -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -static const unsigned char base64_enc_map[64] = -{ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '+', '/' -}; - -static const unsigned char base64_dec_map[128] = -{ - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, - 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 127, 127, 127, 127, 127 -}; - -#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ - -/* - * Encode a buffer into base64 format - */ -int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ) -{ - size_t i, n; - int C1, C2, C3; - unsigned char *p; - - if( slen == 0 ) - { - *olen = 0; - return( 0 ); - } - - n = slen / 3 + ( slen % 3 != 0 ); - - if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) - { - *olen = BASE64_SIZE_T_MAX; - return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - n *= 4; - - if( ( dlen < n + 1 ) || ( NULL == dst ) ) - { - *olen = n + 1; - return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - n = ( slen / 3 ) * 3; - - for( i = 0, p = dst; i < n; i += 3 ) - { - C1 = *src++; - C2 = *src++; - C3 = *src++; - - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; - *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; - *p++ = base64_enc_map[C3 & 0x3F]; - } - - if( i < slen ) - { - C1 = *src++; - C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; - - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; - - if( ( i + 1 ) < slen ) - *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; - else *p++ = '='; - - *p++ = '='; - } - - *olen = p - dst; - *p = 0; - - return( 0 ); -} - -/* - * Decode a base64-formatted buffer - */ -int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ) -{ - size_t i, n; - uint32_t j, x; - unsigned char *p; - - /* First pass: check for validity and get output length */ - for( i = n = j = 0; i < slen; i++ ) - { - /* Skip spaces before checking for EOL */ - x = 0; - while( i < slen && src[i] == ' ' ) - { - ++i; - ++x; - } - - /* Spaces at end of buffer are OK */ - if( i == slen ) - break; - - if( ( slen - i ) >= 2 && - src[i] == '\r' && src[i + 1] == '\n' ) - continue; - - if( src[i] == '\n' ) - continue; - - /* Space inside a line is an error */ - if( x != 0 ) - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - - if( src[i] == '=' && ++j > 2 ) - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - - if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - - if( base64_dec_map[src[i]] < 64 && j != 0 ) - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - - n++; - } - - if( n == 0 ) - { - *olen = 0; - return( 0 ); - } - - /* The following expression is to calculate the following formula without - * risk of integer overflow in n: - * n = ( ( n * 6 ) + 7 ) >> 3; - */ - n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); - n -= j; - - if( dst == NULL || dlen < n ) - { - *olen = n; - return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) - { - if( *src == '\r' || *src == '\n' || *src == ' ' ) - continue; - - j -= ( base64_dec_map[*src] == 64 ); - x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); - - if( ++n == 4 ) - { - n = 0; - if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); - if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); - if( j > 2 ) *p++ = (unsigned char)( x ); - } - } - - *olen = p - dst; - - return( 0 ); -} - -#if defined(MBEDTLS_SELF_TEST) - -static const unsigned char base64_test_dec[64] = -{ - 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, - 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, - 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, - 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, - 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, - 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, - 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, - 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 -}; - -static const unsigned char base64_test_enc[] = - "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" - "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; - -/* - * Checkup routine - */ -int mbedtls_base64_self_test( int verbose ) -{ - size_t len; - const unsigned char *src; - unsigned char buffer[128]; - - if( verbose != 0 ) - mbedtls_printf( " Base64 encoding test: " ); - - src = base64_test_dec; - - if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || - memcmp( base64_test_enc, buffer, 88 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n Base64 decoding test: " ); - - src = base64_test_enc; - - if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || - memcmp( base64_test_dec, buffer, 64 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_BASE64_C */ diff --git a/components/security/mbedtls/src/bignum.c b/components/security/mbedtls/src/bignum.c deleted file mode 100644 index 4a19c52c..00000000 --- a/components/security/mbedtls/src/bignum.c +++ /dev/null @@ -1,2450 +0,0 @@ -/* - * Multi-precision integer library - * - * 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) - */ - -/* - * The following sources were referenced in the design of this Multi-precision - * Integer library: - * - * [1] Handbook of Applied Cryptography - 1997 - * Menezes, van Oorschot and Vanstone - * - * [2] Multi-Precision Math - * Tom St Denis - * https://github.com/libtom/libtommath/blob/develop/tommath.pdf - * - * [3] GNU Multi-Precision Arithmetic Library - * https://gmplib.org/manual/index.html - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_BIGNUM_C) - -#include "mbedtls/bignum.h" -#include "mbedtls/bn_mul.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { - volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; -} - -#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ -#define biL (ciL << 3) /* bits in limb */ -#define biH (ciL << 2) /* half limb size */ - -#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ - -/* - * Convert between bits/chars and number of limbs - * Divide first in order to avoid potential overflows - */ -#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) -#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) - -/* - * Initialize one MPI - */ -void mbedtls_mpi_init( mbedtls_mpi *X ) -{ - if( X == NULL ) - return; - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Unallocate one MPI - */ -void mbedtls_mpi_free( mbedtls_mpi *X ) -{ - if( X == NULL ) - return; - - if( X->p != NULL ) - { - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Enlarge to the specified number of limbs - */ -int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) -{ - mbedtls_mpi_uint *p; - - if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->n < nblimbs ) - { - if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->p != NULL ) - { - memcpy( p, X->p, X->n * ciL ); - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->n = nblimbs; - X->p = p; - } - - return( 0 ); -} - -/* - * Resize down as much as possible, - * while keeping at least the specified number of limbs - */ -int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) -{ - mbedtls_mpi_uint *p; - size_t i; - - /* Actually resize up in this case */ - if( X->n <= nblimbs ) - return( mbedtls_mpi_grow( X, nblimbs ) ); - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - i++; - - if( i < nblimbs ) - i = nblimbs; - - if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->p != NULL ) - { - memcpy( p, X->p, i * ciL ); - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->n = i; - X->p = p; - - return( 0 ); -} - -/* - * Copy the contents of Y into X - */ -int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - int ret; - size_t i; - - if( X == Y ) - return( 0 ); - - if( Y->p == NULL ) - { - mbedtls_mpi_free( X ); - return( 0 ); - } - - for( i = Y->n - 1; i > 0; i-- ) - if( Y->p[i] != 0 ) - break; - i++; - - X->s = Y->s; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); - - memset( X->p, 0, X->n * ciL ); - memcpy( X->p, Y->p, i * ciL ); - -cleanup: - - return( ret ); -} - -/* - * Swap the contents of X and Y - */ -void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) -{ - mbedtls_mpi T; - - memcpy( &T, X, sizeof( mbedtls_mpi ) ); - memcpy( X, Y, sizeof( mbedtls_mpi ) ); - memcpy( Y, &T, sizeof( mbedtls_mpi ) ); -} - -/* - * Conditionally assign X = Y, without leaking information - * about whether the assignment was made or not. - * (Leaking information about the respective sizes of X and Y is ok however.) - */ -int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) -{ - int ret = 0; - size_t i; - - /* make sure assign is 0 or 1 in a time-constant manner */ - assign = (assign | (unsigned char)-assign) >> 7; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); - - X->s = X->s * ( 1 - assign ) + Y->s * assign; - - for( i = 0; i < Y->n; i++ ) - X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; - - for( ; i < X->n; i++ ) - X->p[i] *= ( 1 - assign ); - -cleanup: - return( ret ); -} - -/* - * Conditionally swap X and Y, without leaking information - * about whether the swap was made or not. - * Here it is not ok to simply swap the pointers, which whould lead to - * different memory access patterns when X and Y are used afterwards. - */ -int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) -{ - int ret, s; - size_t i; - mbedtls_mpi_uint tmp; - - if( X == Y ) - return( 0 ); - - /* make sure swap is 0 or 1 in a time-constant manner */ - swap = (swap | (unsigned char)-swap) >> 7; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); - - s = X->s; - X->s = X->s * ( 1 - swap ) + Y->s * swap; - Y->s = Y->s * ( 1 - swap ) + s * swap; - - - for( i = 0; i < X->n; i++ ) - { - tmp = X->p[i]; - X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; - Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; - } - -cleanup: - return( ret ); -} - -/* - * Set value from integer - */ -int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); - memset( X->p, 0, X->n * ciL ); - - X->p[0] = ( z < 0 ) ? -z : z; - X->s = ( z < 0 ) ? -1 : 1; - -cleanup: - - return( ret ); -} - -/* - * Get a specific bit - */ -int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) -{ - if( X->n * biL <= pos ) - return( 0 ); - - return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); -} - -/* - * Set a bit to a specific value of 0 or 1 - */ -int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) -{ - int ret = 0; - size_t off = pos / biL; - size_t idx = pos % biL; - - if( val != 0 && val != 1 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - if( X->n * biL <= pos ) - { - if( val == 0 ) - return( 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); - } - - X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); - X->p[off] |= (mbedtls_mpi_uint) val << idx; - -cleanup: - - return( ret ); -} - -/* - * Return the number of less significant zero-bits - */ -size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) -{ - size_t i, j, count = 0; - - for( i = 0; i < X->n; i++ ) - for( j = 0; j < biL; j++, count++ ) - if( ( ( X->p[i] >> j ) & 1 ) != 0 ) - return( count ); - - return( 0 ); -} - -/* - * Count leading zero bits in a given integer - */ -static size_t mbedtls_clz( const mbedtls_mpi_uint x ) -{ - size_t j; - mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); - - for( j = 0; j < biL; j++ ) - { - if( x & mask ) break; - - mask >>= 1; - } - - return j; -} - -/* - * Return the number of bits - */ -size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) -{ - size_t i, j; - - if( X->n == 0 ) - return( 0 ); - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - - j = biL - mbedtls_clz( X->p[i] ); - - return( ( i * biL ) + j ); -} - -/* - * Return the total size in bytes - */ -size_t mbedtls_mpi_size( const mbedtls_mpi *X ) -{ - return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); -} - -/* - * Convert an ASCII character to digit value - */ -static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) -{ - *d = 255; - - if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; - if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; - if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; - - if( *d >= (mbedtls_mpi_uint) radix ) - return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); - - return( 0 ); -} - -/* - * Import from an ASCII string - */ -int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) -{ - int ret; - size_t i, j, slen, n; - mbedtls_mpi_uint d; - mbedtls_mpi T; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &T ); - - slen = strlen( s ); - - if( radix == 16 ) - { - if( slen > MPI_SIZE_T_MAX >> 2 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - n = BITS_TO_LIMBS( slen << 2 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = slen, j = 0; i > 0; i--, j++ ) - { - if( i == 1 && s[i - 1] == '-' ) - { - X->s = -1; - break; - } - - MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); - X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = 0; i < slen; i++ ) - { - if( i == 0 && s[i] == '-' ) - { - X->s = -1; - continue; - } - - MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); - - if( X->s == 1 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); - } - } - } - -cleanup: - - mbedtls_mpi_free( &T ); - - return( ret ); -} - -/* - * Helper to write the digits high-order first - */ -static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) -{ - int ret; - mbedtls_mpi_uint r; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); - - if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) - MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); - - if( r < 10 ) - *(*p)++ = (char)( r + 0x30 ); - else - *(*p)++ = (char)( r + 0x37 ); - -cleanup: - - return( ret ); -} - -/* - * Export into an ASCII string - */ -int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, - char *buf, size_t buflen, size_t *olen ) -{ - int ret = 0; - size_t n; - char *p; - mbedtls_mpi T; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - n = mbedtls_mpi_bitlen( X ); - if( radix >= 4 ) n >>= 1; - if( radix >= 16 ) n >>= 1; - /* - * Round up the buffer length to an even value to ensure that there is - * enough room for hexadecimal values that can be represented in an odd - * number of digits. - */ - n += 3 + ( ( n + 1 ) & 1 ); - - if( buflen < n ) - { - *olen = n; - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - } - - p = buf; - mbedtls_mpi_init( &T ); - - if( X->s == -1 ) - *p++ = '-'; - - if( radix == 16 ) - { - int c; - size_t i, j, k; - - for( i = X->n, k = 0; i > 0; i-- ) - { - for( j = ciL; j > 0; j-- ) - { - c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; - - if( c == 0 && k == 0 && ( i + j ) != 2 ) - continue; - - *(p++) = "0123456789ABCDEF" [c / 16]; - *(p++) = "0123456789ABCDEF" [c % 16]; - k = 1; - } - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); - - if( T.s == -1 ) - T.s = 1; - - MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); - } - - *p++ = '\0'; - *olen = p - buf; - -cleanup: - - mbedtls_mpi_free( &T ); - - return( ret ); -} - -#if defined(MBEDTLS_FS_IO) -#if 0 -/* - * Read X from an opened file - */ -int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) -{ - mbedtls_mpi_uint d; - size_t slen; - char *p; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; - - memset( s, 0, sizeof( s ) ); - if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) - return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); - - slen = strlen( s ); - if( slen == sizeof( s ) - 2 ) - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - - if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } - if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } - - p = s + slen; - while( --p >= s ) - if( mpi_get_digit( &d, radix, *p ) != 0 ) - break; - - return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); -} - -/* - * Write X into an opened file (or stdout if fout == NULL) - */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) -{ - int ret; - size_t n, slen, plen; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; - - memset( s, 0, sizeof( s ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); - - if( p == NULL ) p = ""; - - plen = strlen( p ); - slen = strlen( s ); - s[slen++] = '\r'; - s[slen++] = '\n'; - - if( fout != NULL ) - { - if( fwrite( p, 1, plen, fout ) != plen || - fwrite( s, 1, slen, fout ) != slen ) - return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); - } - else - mbedtls_printf( "%s%s", p, s ); - -cleanup: - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ -#endif - -/* - * Import X from unsigned binary data, big endian - */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t i, j, n; - - for( n = 0; n < buflen; n++ ) - if( buf[n] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = buflen, j = 0; i > n; i--, j++ ) - X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); - -cleanup: - - return( ret ); -} - -/* - * Export X into unsigned binary data, big endian - */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) -{ - size_t i, j, n; - - n = mbedtls_mpi_size( X ); - - if( buflen < n ) - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - - memset( buf, 0, buflen ); - - for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) - buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); - - return( 0 ); -} - -/* - * Left-shift: X <<= count - */ -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) -{ - int ret; - size_t i, v0, t1; - mbedtls_mpi_uint r0 = 0, r1; - - v0 = count / (biL ); - t1 = count & (biL - 1); - - i = mbedtls_mpi_bitlen( X ) + count; - - if( X->n * biL < i ) - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); - - ret = 0; - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = X->n; i > v0; i-- ) - X->p[i - 1] = X->p[i - v0 - 1]; - - for( ; i > 0; i-- ) - X->p[i - 1] = 0; - } - - /* - * shift by count % limb_size - */ - if( t1 > 0 ) - { - for( i = v0; i < X->n; i++ ) - { - r1 = X->p[i] >> (biL - t1); - X->p[i] <<= t1; - X->p[i] |= r0; - r0 = r1; - } - } - -cleanup: - - return( ret ); -} - -/* - * Right-shift: X >>= count - */ -int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) -{ - size_t i, v0, v1; - mbedtls_mpi_uint r0 = 0, r1; - - v0 = count / biL; - v1 = count & (biL - 1); - - if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) - return mbedtls_mpi_lset( X, 0 ); - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = 0; i < X->n - v0; i++ ) - X->p[i] = X->p[i + v0]; - - for( ; i < X->n; i++ ) - X->p[i] = 0; - } - - /* - * shift by count % limb_size - */ - if( v1 > 0 ) - { - for( i = X->n; i > 0; i-- ) - { - r1 = X->p[i - 1] << (biL - v1); - X->p[i - 1] >>= v1; - X->p[i - 1] |= r0; - r0 = r1; - } - } - - return( 0 ); -} - -/* - * Compare unsigned values - */ -int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( 1 ); - if( j > i ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( X->s ); - if( j > i ) return( -Y->s ); - - if( X->s > 0 && Y->s < 0 ) return( 1 ); - if( Y->s > 0 && X->s < 0 ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) -{ - mbedtls_mpi Y; - mbedtls_mpi_uint p[1]; - - *p = ( z < 0 ) ? -z : z; - Y.s = ( z < 0 ) ? -1 : 1; - Y.n = 1; - Y.p = p; - - return( mbedtls_mpi_cmp_mpi( X, &Y ) ); -} - -/* - * Unsigned addition: X = |A| + |B| (HAC 14.7) - */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, j; - mbedtls_mpi_uint *o, *p, c, tmp; - - if( X == B ) - { - const mbedtls_mpi *T = A; A = X; B = T; - } - - if( X != A ) - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned additions. - */ - X->s = 1; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); - - o = B->p; p = X->p; c = 0; - - /* - * tmp is used because it might happen that p == o - */ - for( i = 0; i < j; i++, o++, p++ ) - { - tmp= *o; - *p += c; c = ( *p < c ); - *p += tmp; c += ( *p < tmp ); - } - - while( c != 0 ) - { - if( i >= X->n ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); - p = X->p + i; - } - - *p += c; c = ( *p < c ); i++; p++; - } - -cleanup: - - return( ret ); -} - -/* - * Helper for mbedtls_mpi subtraction - */ -static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) -{ - size_t i; - mbedtls_mpi_uint c, z; - - for( i = c = 0; i < n; i++, s++, d++ ) - { - z = ( *d < c ); *d -= c; - c = ( *d < *s ) + z; *d -= *s; - } - - while( c != 0 ) - { - z = ( *d < c ); *d -= c; - c = z; i++; d++; - } -} - -/* - * Unsigned subtraction: X = |A| - |B| (HAC 14.9) - */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - mbedtls_mpi TB; - int ret; - size_t n; - - if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - mbedtls_mpi_init( &TB ); - - if( X == B ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); - B = &TB; - } - - if( X != A ) - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned subtractions. - */ - X->s = 1; - - ret = 0; - - for( n = B->n; n > 0; n-- ) - if( B->p[n - 1] != 0 ) - break; - - mpi_sub_hlp( n, B->p, X->p ); - -cleanup: - - mbedtls_mpi_free( &TB ); - - return( ret ); -} - -/* - * Signed addition: X = A + B - */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s < 0 ) - { - if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed subtraction: X = A - B - */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s > 0 ) - { - if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed addition: X = A + b - */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_add_mpi( X, A, &_B ) ); -} - -/* - * Signed subtraction: X = A - b - */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); -} - -/* - * Helper for mbedtls_mpi multiplication - */ -static -#if defined(__APPLE__) && defined(__arm__) -/* - * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) - * appears to need this to prevent bad ARM code generation at -O3. - */ -__attribute__ ((noinline)) -#endif -void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) -{ - mbedtls_mpi_uint c = 0, t = 0; - -#if defined(MULADDC_HUIT) - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_HUIT - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#else /* MULADDC_HUIT */ - for( ; i >= 16; i -= 16 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#endif /* MULADDC_HUIT */ - - t++; - - do { - *d += c; c = ( *d < c ); d++; - } - while( c != 0 ); -} - -/* - * Baseline multiplication: X = A * B (HAC 14.12) - */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, j; - mbedtls_mpi TA, TB; - - mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); - - if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } - if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } - - for( i = A->n; i > 0; i-- ) - if( A->p[i - 1] != 0 ) - break; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i++; j > 0; j-- ) - mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); - - X->s = A->s * B->s; - -cleanup: - - mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); - - return( ret ); -} - -/* - * Baseline multiplication: X = A * b - */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - _B.s = 1; - _B.n = 1; - _B.p = p; - p[0] = b; - - return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); -} - -/* - * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and - * mbedtls_mpi_uint divisor, d - */ -static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, - mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) -{ -#if defined(MBEDTLS_HAVE_UDBL) - mbedtls_t_udbl dividend, quotient; -#else - const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; - const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; - mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; - mbedtls_mpi_uint u0_msw, u0_lsw; - size_t s; -#endif - - /* - * Check for overflow - */ - if( 0 == d || u1 >= d ) - { - if (r != NULL) *r = ~0; - - return ( ~0 ); - } - -#if defined(MBEDTLS_HAVE_UDBL) - dividend = (mbedtls_t_udbl) u1 << biL; - dividend |= (mbedtls_t_udbl) u0; - quotient = dividend / d; - if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) - quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; - - if( r != NULL ) - *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); - - return (mbedtls_mpi_uint) quotient; -#else - - /* - * Algorithm D, Section 4.3.1 - The Art of Computer Programming - * Vol. 2 - Seminumerical Algorithms, Knuth - */ - - /* - * Normalize the divisor, d, and dividend, u0, u1 - */ - s = mbedtls_clz( d ); - d = d << s; - - u1 = u1 << s; - u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); - u0 = u0 << s; - - d1 = d >> biH; - d0 = d & uint_halfword_mask; - - u0_msw = u0 >> biH; - u0_lsw = u0 & uint_halfword_mask; - - /* - * Find the first quotient and remainder - */ - q1 = u1 / d1; - r0 = u1 - d1 * q1; - - while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) - { - q1 -= 1; - r0 += d1; - - if ( r0 >= radix ) break; - } - - rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); - q0 = rAX / d1; - r0 = rAX - q0 * d1; - - while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) - { - q0 -= 1; - r0 += d1; - - if ( r0 >= radix ) break; - } - - if (r != NULL) - *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; - - quotient = q1 * radix + q0; - - return quotient; -#endif -} - -/* - * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) - */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, n, t, k; - mbedtls_mpi X, Y, Z, T1, T2; - - if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) - return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); - - mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); - mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); - - if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) - { - if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); - if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); - return( 0 ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); - X.s = Y.s = 1; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); - - k = mbedtls_mpi_bitlen( &Y ) % biL; - if( k < biL - 1 ) - { - k = biL - 1 - k; - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); - } - else k = 0; - - n = X.n - 1; - t = Y.n - 1; - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); - - while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) - { - Z.p[n - t]++; - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); - } - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); - - for( i = n; i > t ; i-- ) - { - if( X.p[i] >= Y.p[t] ) - Z.p[i - t - 1] = ~0; - else - { - Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], - Y.p[t], NULL); - } - - Z.p[i - t - 1]++; - do - { - Z.p[i - t - 1]--; - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); - T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; - T1.p[1] = Y.p[t]; - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); - T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; - T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; - T2.p[2] = X.p[i]; - } - while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); - - if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); - Z.p[i - t - 1]--; - } - } - - if( Q != NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); - Q->s = A->s * B->s; - } - - if( R != NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); - X.s = A->s; - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); - - if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) - R->s = 1; - } - -cleanup: - - mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); - mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); - - return( ret ); -} - -/* - * Division by int: A = Q * b + R - */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); -} - -/* - * Modulo: R = A mod B - */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - - if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); - - while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); - - while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); - -cleanup: - - return( ret ); -} - -/* - * Modulo: r = A mod b - */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - size_t i; - mbedtls_mpi_uint x, y, z; - - if( b == 0 ) - return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); - - if( b < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - /* - * handle trivial cases - */ - if( b == 1 ) - { - *r = 0; - return( 0 ); - } - - if( b == 2 ) - { - *r = A->p[0] & 1; - return( 0 ); - } - - /* - * general case - */ - for( i = A->n, y = 0; i > 0; i-- ) - { - x = A->p[i - 1]; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - - x <<= biH; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - } - - /* - * If A is negative, then the current y represents a negative value. - * Flipping it to the positive side. - */ - if( A->s < 0 && y != 0 ) - y = b - y; - - *r = y; - - return( 0 ); -} - -/* - * Fast Montgomery initialization (thanks to Tom St Denis) - */ -static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) -{ - mbedtls_mpi_uint x, m0 = N->p[0]; - unsigned int i; - - x = m0; - x += ( ( m0 + 2 ) & 4 ) << 1; - - for( i = biL; i >= 8; i /= 2 ) - x *= ( 2 - ( m0 * x ) ); - - *mm = ~x + 1; -} - -/* - * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) - */ -static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, - const mbedtls_mpi *T ) -{ - size_t i, n, m; - mbedtls_mpi_uint u0, u1, *d; - - if( T->n < N->n + 1 || T->p == NULL ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - memset( T->p, 0, T->n * ciL ); - - d = T->p; - n = N->n; - m = ( B->n < n ) ? B->n : n; - - for( i = 0; i < n; i++ ) - { - /* - * T = (T + u0*B + u1*N) / 2^biL - */ - u0 = A->p[i]; - u1 = ( d[0] + u0 * B->p[0] ) * mm; - - mpi_mul_hlp( m, B->p, d, u0 ); - mpi_mul_hlp( n, N->p, d, u1 ); - - *d++ = u0; d[n + 1] = 0; - } - - memcpy( A->p, d, ( n + 1 ) * ciL ); - - if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) - mpi_sub_hlp( n, N->p, A->p ); - else - /* prevent timing attacks */ - mpi_sub_hlp( n, A->p, T->p ); - - return( 0 ); -} - -/* - * Montgomery reduction: A = A * R^-1 mod N - */ -static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) -{ - mbedtls_mpi_uint z = 1; - mbedtls_mpi U; - - U.n = U.s = (int) z; - U.p = &z; - - return( mpi_montmul( A, &U, N, mm, T ) ); -} - -/* - * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) - */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) -{ - int ret; - size_t wbits, wsize, one = 1; - size_t i, j, nblimbs; - size_t bufsize, nbits; - mbedtls_mpi_uint ei, mm, state; - mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; - int neg; - - if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - /* - * Init temps and window size - */ - mpi_montg_init( &mm, N ); - mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); - mbedtls_mpi_init( &Apos ); - memset( W, 0, sizeof( W ) ); - - i = mbedtls_mpi_bitlen( E ); - - wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : - ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; - - if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) - wsize = MBEDTLS_MPI_WINDOW_SIZE; - - j = N->n + 1; - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); - - /* - * Compensate for negative A (and correct at the end) - */ - neg = ( A->s == -1 ); - if( neg ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); - Apos.s = 1; - A = &Apos; - } - - /* - * If 1st call, pre-compute R^2 mod N - */ - if( _RR == NULL || _RR->p == NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); - - if( _RR != NULL ) - memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); - } - else - memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); - - /* - * W[1] = A * R^2 * R^-1 mod N = A * R mod N - */ - if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); - else - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); - - MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); - - /* - * X = R^2 * R^-1 mod N = R mod N - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); - MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); - - if( wsize > 1 ) - { - /* - * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) - */ - j = one << ( wsize - 1 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); - - for( i = 0; i < wsize - 1; i++ ) - MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); - - /* - * W[i] = W[i - 1] * W[1] - */ - for( i = j + 1; i < ( one << wsize ); i++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); - - MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); - } - } - - nblimbs = E->n; - bufsize = 0; - nbits = 0; - wbits = 0; - state = 0; - - while( 1 ) - { - if( bufsize == 0 ) - { - if( nblimbs == 0 ) - break; - - nblimbs--; - - bufsize = sizeof( mbedtls_mpi_uint ) << 3; - } - - bufsize--; - - ei = (E->p[nblimbs] >> bufsize) & 1; - - /* - * skip leading 0s - */ - if( ei == 0 && state == 0 ) - continue; - - if( ei == 0 && state == 1 ) - { - /* - * out of window, square X - */ - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - continue; - } - - /* - * add ei to current window - */ - state = 2; - - nbits++; - wbits |= ( ei << ( wsize - nbits ) ); - - if( nbits == wsize ) - { - /* - * X = X^wsize R^-1 mod N - */ - for( i = 0; i < wsize; i++ ) - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - - /* - * X = X * W[wbits] R^-1 mod N - */ - MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); - - state--; - nbits = 0; - wbits = 0; - } - } - - /* - * process the remaining bits - */ - for( i = 0; i < nbits; i++ ) - { - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - - wbits <<= 1; - - if( ( wbits & ( one << wsize ) ) != 0 ) - MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); - } - - /* - * X = A^E * R * R^-1 mod N = A^E mod N - */ - MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); - - if( neg ) - { - X->s = -1; - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); - } - -cleanup: - - for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) - mbedtls_mpi_free( &W[i] ); - - mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); - - if( _RR == NULL || _RR->p == NULL ) - mbedtls_mpi_free( &RR ); - - return( ret ); -} - -/* - * Greatest common divisor: G = gcd(A, B) (HAC 14.54) - */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t lz, lzt; - mbedtls_mpi TG, TA, TB; - - mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); - - lz = mbedtls_mpi_lsb( &TA ); - lzt = mbedtls_mpi_lsb( &TB ); - - if( lzt < lz ) - lz = lzt; - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); - - TA.s = TB.s = 1; - - while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); - - if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); - } - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); - -cleanup: - - mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); - - return( ret ); -} - -/* - * Fill X with size bytes of random. - * - * Use a temporary bytes representation to make sure the result is the same - * regardless of the platform endianness (useful when f_rng is actually - * deterministic, eg for tests). - */ -int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( size > MBEDTLS_MPI_MAX_SIZE ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); - -cleanup: - return( ret ); -} - -/* - * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) - */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) -{ - int ret; - mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; - - if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); - mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); - mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); - - if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - goto cleanup; - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); - - do - { - while( ( TU.p[0] & 1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); - - if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); - } - - while( ( TV.p[0] & 1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); - - if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); - } - - if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); - } - } - while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); - - while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); - - while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); - -cleanup: - - mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); - mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); - mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); - - return( ret ); -} - -#if defined(MBEDTLS_GENPRIME) - -static const int small_prime[] = -{ - 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, - 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, - 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, - 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, - 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, - 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, - 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997, -103 -}; - -/* - * Small divisors test (X must be positive) - * - * Return values: - * 0: no small factor (possible prime, more tests needed) - * 1: certain prime - * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime - * other negative: error - */ -static int mpi_check_small_factors( const mbedtls_mpi *X ) -{ - int ret = 0; - size_t i; - mbedtls_mpi_uint r; - - if( ( X->p[0] & 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - - for( i = 0; small_prime[i] > 0; i++ ) - { - if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) - return( 1 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); - - if( r == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - } - -cleanup: - return( ret ); -} - -/* - * Miller-Rabin pseudo-primality test (HAC 4.24) - */ -static int mpi_miller_rabin( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count; - size_t i, j, k, n, s; - mbedtls_mpi W, R, T, A, RR; - - mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); - mbedtls_mpi_init( &RR ); - - /* - * W = |X| - 1 - * R = W >> lsb( W ) - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); - s = mbedtls_mpi_lsb( &W ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); - - i = mbedtls_mpi_bitlen( X ); - /* - * HAC, table 4.4 - */ - n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : - ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : - ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); - - for( i = 0; i < n; i++ ) - { - /* - * pick a random A, 1 < A < |X| - 1 - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) - { - j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); - } - A.p[0] |= 3; - - count = 0; - do { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - j = mbedtls_mpi_bitlen( &A ); - k = mbedtls_mpi_bitlen( &W ); - if (j > k) { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); - } - - if (count++ > 30) { - return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - } - - } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || - mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); - - /* - * A = A^R mod |X| - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); - - if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || - mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - continue; - - j = 1; - while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) - { - /* - * A = A * A mod |X| - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); - - if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - break; - - j++; - } - - /* - * not prime if A != |X| - 1 or A == 1 - */ - if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || - mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - { - ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - break; - } - } - -cleanup: - mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); - mbedtls_mpi_free( &RR ); - - return( ret ); -} - -/* - * Pseudo-primality test: small factors, then Miller-Rabin - */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi XX; - - XX.s = 1; - XX.n = X->n; - XX.p = X->p; - - if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || - mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - - if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) - return( 0 ); - - if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) - { - if( ret == 1 ) - return( 0 ); - - return( ret ); - } - - return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); -} - -/* - * Prime number generation - */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t k, n; - mbedtls_mpi_uint r; - mbedtls_mpi Y; - - if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &Y ); - - n = BITS_TO_LIMBS( nbits ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); - - k = mbedtls_mpi_bitlen( X ); - if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); - - mbedtls_mpi_set_bit( X, nbits-1, 1 ); - - X->p[0] |= 1; - - if( dh_flag == 0 ) - { - while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) - { - if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); - } - } - else - { - /* - * An necessary condition for Y and X = 2Y + 1 to be prime - * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). - * Make sure it is satisfied, while keeping X = 3 mod 4 - */ - - X->p[0] |= 2; - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); - if( r == 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); - else if( r == 1 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); - - /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); - - while( 1 ) - { - /* - * First, check small factors for X and Y - * before doing Miller-Rabin on any of them - */ - if( ( ret = mpi_check_small_factors( X ) ) == 0 && - ( ret = mpi_check_small_factors( &Y ) ) == 0 && - ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && - ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) - { - break; - } - - if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - /* - * Next candidates. We want to preserve Y = (X-1) / 2 and - * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) - * so up Y by 6 and X by 12. - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); - } - } - -cleanup: - - mbedtls_mpi_free( &Y ); - - return( ret ); -} - -#endif /* MBEDTLS_GENPRIME */ - -#if defined(MBEDTLS_SELF_TEST) - -#define GCD_PAIR_COUNT 3 - -static const int gcd_pairs[GCD_PAIR_COUNT][3] = -{ - { 693, 609, 21 }, - { 1764, 868, 28 }, - { 768454923, 542167814, 1 } -}; - -/* - * Checkup routine - */ -int mbedtls_mpi_self_test( int verbose ) -{ - int ret, i; - mbedtls_mpi A, E, N, X, Y, U, V; - - mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); - mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, - "EFE021C2645FD1DC586E69184AF4A31E" \ - "D5F53E93B5F123FA41680867BA110131" \ - "944FE7952E2517337780CB0DB80E61AA" \ - "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, - "B2E7EFD37075B9F03FF989C7C5051C20" \ - "34D2A323810251127E7BF8625A4F49A5" \ - "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ - "5B5C25763222FEFCCFC38B832366C29E" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, - "0066A198186C18C10B2F5ED9B522752A" \ - "9830B69916E535C8F047518A889A43A5" \ - "94B6BED27A168D31D4A52F88925AA8F5" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "602AB7ECA597A3D6B56FF9829A5E8B85" \ - "9E857EA95A03512E2BAE7391688D264A" \ - "A5663B0341DB9CCFD2C4C5F421FEC814" \ - "8001B72E848A38CAE1C65F78E56ABDEF" \ - "E12D3C039B8A02D6BE593F0BBBDA56F1" \ - "ECF677152EF804370C1A305CAF3B5BF1" \ - "30879B56C61DE584A0F53A2447A51E" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #1 (mul_mpi): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "256567336059E52CAE22925474705F39A94" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, - "6613F26162223DF488E9CD48CC132C7A" \ - "0AC93C701B001B092E4E5B9F73BCD27B" \ - "9EE50D0657C77F374E903CDFA4C642" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #2 (div_mpi): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || - mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "36E139AEA55215609D2816998ED020BB" \ - "BD96C37890F65171D948E9BC7CBAA4D9" \ - "325D24D6A3C12710F10A09FA08AB87" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #3 (exp_mod): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ - "C3DBA76456363A10869622EAC2DD84EC" \ - "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #4 (inv_mod): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #5 (simple gcd): " ); - - for( i = 0; i < GCD_PAIR_COUNT; i++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); - - if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed at %d\n", i ); - - ret = 1; - goto cleanup; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - - if( ret != 0 && verbose != 0 ) - mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); - - mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); - mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_BIGNUM_C */ - diff --git a/components/security/mbedtls/src/blowfish.c b/components/security/mbedtls/src/blowfish.c deleted file mode 100644 index 9003f0df..00000000 --- a/components/security/mbedtls/src/blowfish.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Blowfish implementation - * - * 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) - */ -/* - * The Blowfish block cipher was designed by Bruce Schneier in 1993. - * http://www.schneier.com/blowfish.html - * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_BLOWFISH_C) - -#include "mbedtls/blowfish.h" - -#include - -#if !defined(MBEDTLS_BLOWFISH_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { - 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, - 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, - 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, - 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, - 0x9216D5D9L, 0x8979FB1BL -}; - -/* declarations of data at the end of this file */ -static const uint32_t S[4][256]; - -static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) -{ - unsigned short a, b, c, d; - uint32_t y; - - d = (unsigned short)(x & 0xFF); - x >>= 8; - c = (unsigned short)(x & 0xFF); - x >>= 8; - b = (unsigned short)(x & 0xFF); - x >>= 8; - a = (unsigned short)(x & 0xFF); - y = ctx->S[0][a] + ctx->S[1][b]; - y = y ^ ctx->S[2][c]; - y = y + ctx->S[3][d]; - - return( y ); -} - -static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) -{ - uint32_t Xl, Xr, temp; - short i; - - Xl = *xl; - Xr = *xr; - - for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) - { - Xl = Xl ^ ctx->P[i]; - Xr = F( ctx, Xl ) ^ Xr; - - temp = Xl; - Xl = Xr; - Xr = temp; - } - - temp = Xl; - Xl = Xr; - Xr = temp; - - Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; - Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; - - *xl = Xl; - *xr = Xr; -} - -static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) -{ - uint32_t Xl, Xr, temp; - short i; - - Xl = *xl; - Xr = *xr; - - for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) - { - Xl = Xl ^ ctx->P[i]; - Xr = F( ctx, Xl ) ^ Xr; - - temp = Xl; - Xl = Xr; - Xr = temp; - } - - temp = Xl; - Xl = Xr; - Xr = temp; - - Xr = Xr ^ ctx->P[1]; - Xl = Xl ^ ctx->P[0]; - - *xl = Xl; - *xr = Xr; -} - -void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); -} - -void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); -} - -/* - * Blowfish key schedule - */ -int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - unsigned int i, j, k; - uint32_t data, datal, datar; - - if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || - ( keybits % 8 ) ) - { - return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH ); - } - - keybits >>= 3; - - for( i = 0; i < 4; i++ ) - { - for( j = 0; j < 256; j++ ) - ctx->S[i][j] = S[i][j]; - } - - j = 0; - for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) - { - data = 0x00000000; - for( k = 0; k < 4; ++k ) - { - data = ( data << 8 ) | key[j++]; - if( j >= keybits ) - j = 0; - } - ctx->P[i] = P[i] ^ data; - } - - datal = 0x00000000; - datar = 0x00000000; - - for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) - { - blowfish_enc( ctx, &datal, &datar ); - ctx->P[i] = datal; - ctx->P[i + 1] = datar; - } - - for( i = 0; i < 4; i++ ) - { - for( j = 0; j < 256; j += 2 ) - { - blowfish_enc( ctx, &datal, &datar ); - ctx->S[i][j] = datal; - ctx->S[i][j + 1] = datar; - } - } - return( 0 ); -} - -/* - * Blowfish-ECB block encryption/decryption - */ -int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, - int mode, - const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) -{ - uint32_t X0, X1; - - GET_UINT32_BE( X0, input, 0 ); - GET_UINT32_BE( X1, input, 4 ); - - if( mode == MBEDTLS_BLOWFISH_DECRYPT ) - { - blowfish_dec( ctx, &X0, &X1 ); - } - else /* MBEDTLS_BLOWFISH_ENCRYPT */ - { - blowfish_enc( ctx, &X0, &X1 ); - } - - PUT_UINT32_BE( X0, output, 0 ); - PUT_UINT32_BE( X1, output, 4 ); - - return( 0 ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * Blowfish-CBC buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, - int mode, - size_t length, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; - - if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) - return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_BLOWFISH_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); - mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); - - input += MBEDTLS_BLOWFISH_BLOCKSIZE; - output += MBEDTLS_BLOWFISH_BLOCKSIZE; - length -= MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); - - input += MBEDTLS_BLOWFISH_BLOCKSIZE; - output += MBEDTLS_BLOWFISH_BLOCKSIZE; - length -= MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * Blowfish CFB buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == MBEDTLS_BLOWFISH_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - - *iv_off = n; - - return( 0 ); -} -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * Blowfish CTR buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, - stream_block ); - - for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static const uint32_t S[4][256] = { - { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, - 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, - 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, - 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, - 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, - 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, - 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, - 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, - 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, - 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, - 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, - 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, - 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, - 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, - 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, - 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, - 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, - 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, - 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, - 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, - 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, - 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, - 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, - 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, - 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, - 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, - 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, - 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, - 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, - 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, - 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, - 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, - 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, - 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, - 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, - 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, - 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, - 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, - 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, - 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, - 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, - 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, - 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, - 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, - 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, - 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, - 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, - 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, - 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, - 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, - 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, - 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, - 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, - 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, - 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, - 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, - 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, - 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, - 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, - 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, - 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, - 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, - 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, - 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, - { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, - 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, - 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, - 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, - 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, - 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, - 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, - 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, - 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, - 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, - 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, - 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, - 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, - 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, - 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, - 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, - 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, - 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, - 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, - 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, - 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, - 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, - 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, - 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, - 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, - 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, - 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, - 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, - 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, - 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, - 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, - 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, - 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, - 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, - 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, - 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, - 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, - 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, - 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, - 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, - 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, - 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, - 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, - 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, - 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, - 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, - 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, - 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, - 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, - 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, - 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, - 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, - 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, - 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, - 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, - 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, - 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, - 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, - 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, - 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, - 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, - 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, - 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, - 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, - { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, - 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, - 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, - 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, - 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, - 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, - 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, - 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, - 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, - 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, - 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, - 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, - 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, - 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, - 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, - 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, - 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, - 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, - 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, - 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, - 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, - 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, - 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, - 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, - 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, - 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, - 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, - 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, - 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, - 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, - 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, - 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, - 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, - 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, - 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, - 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, - 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, - 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, - 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, - 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, - 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, - 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, - 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, - 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, - 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, - 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, - 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, - 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, - 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, - 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, - 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, - 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, - 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, - 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, - 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, - 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, - 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, - 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, - 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, - 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, - 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, - 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, - 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, - 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, - { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, - 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, - 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, - 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, - 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, - 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, - 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, - 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, - 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, - 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, - 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, - 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, - 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, - 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, - 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, - 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, - 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, - 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, - 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, - 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, - 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, - 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, - 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, - 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, - 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, - 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, - 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, - 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, - 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, - 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, - 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, - 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, - 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, - 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, - 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, - 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, - 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, - 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, - 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, - 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, - 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, - 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, - 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, - 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, - 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, - 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, - 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, - 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, - 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, - 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, - 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, - 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, - 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, - 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, - 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, - 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, - 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, - 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, - 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, - 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, - 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, - 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, - 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, - 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } -}; - -#endif /* !MBEDTLS_BLOWFISH_ALT */ -#endif /* MBEDTLS_BLOWFISH_C */ diff --git a/components/security/mbedtls/src/camellia.c b/components/security/mbedtls/src/camellia.c deleted file mode 100644 index ac6f96a8..00000000 --- a/components/security/mbedtls/src/camellia.c +++ /dev/null @@ -1,1072 +0,0 @@ -/* - * Camellia implementation - * - * 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) - */ -/* - * The Camellia block cipher was designed by NTT and Mitsubishi Electric - * Corporation. - * - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CAMELLIA_C) - -#include "mbedtls/camellia.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_CAMELLIA_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -static const unsigned char SIGMA_CHARS[6][8] = -{ - { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, - { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, - { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, - { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, - { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, - { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } -}; - -#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) - -static const unsigned char FSb[256] = -{ - 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, - 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, - 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, - 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, - 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, - 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, - 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, - 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, - 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, - 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, - 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, - 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, - 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, - 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, - 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, - 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 -}; - -#define SBOX1(n) FSb[(n)] -#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) -#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) -#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] - -#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ - -static const unsigned char FSb[256] = -{ - 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, - 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, - 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, - 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, - 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, - 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, - 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, - 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, - 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, - 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, - 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, - 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, - 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, - 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, - 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, - 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 -}; - -static const unsigned char FSb2[256] = -{ - 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, - 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, - 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, - 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, - 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, - 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, - 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, - 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, - 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, - 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, - 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, - 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, - 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, - 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, - 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, - 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 -}; - -static const unsigned char FSb3[256] = -{ - 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, - 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, - 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, - 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, - 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, - 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, - 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, - 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, - 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, - 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, - 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, - 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, - 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, - 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, - 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, - 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 -}; - -static const unsigned char FSb4[256] = -{ - 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, - 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, - 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, - 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, - 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, - 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, - 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, - 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, - 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, - 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, - 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, - 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, - 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, - 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, - 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, - 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 -}; - -#define SBOX1(n) FSb[(n)] -#define SBOX2(n) FSb2[(n)] -#define SBOX3(n) FSb3[(n)] -#define SBOX4(n) FSb4[(n)] - -#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ - -static const unsigned char shifts[2][4][4] = -{ - { - { 1, 1, 1, 1 }, /* KL */ - { 0, 0, 0, 0 }, /* KR */ - { 1, 1, 1, 1 }, /* KA */ - { 0, 0, 0, 0 } /* KB */ - }, - { - { 1, 0, 1, 1 }, /* KL */ - { 1, 1, 0, 1 }, /* KR */ - { 1, 1, 1, 0 }, /* KA */ - { 1, 1, 0, 1 } /* KB */ - } -}; - -static const signed char indexes[2][4][20] = -{ - { - { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, - 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ - { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, - 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ - }, - { - { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, - -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ - { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, - 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ - { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, - 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ - { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, - 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ - } -}; - -static const signed char transposes[2][20] = -{ - { - 21, 22, 23, 20, - -1, -1, -1, -1, - 18, 19, 16, 17, - 11, 8, 9, 10, - 15, 12, 13, 14 - }, - { - 25, 26, 27, 24, - 29, 30, 31, 28, - 18, 19, 16, 17, - -1, -1, -1, -1, - -1, -1, -1, -1 - } -}; - -/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ -#define ROTL(DEST, SRC, SHIFT) \ -{ \ - (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ - (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ - (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ - (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ -} - -#define FL(XL, XR, KL, KR) \ -{ \ - (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ - (XL) = ((XR) | (KR)) ^ (XL); \ -} - -#define FLInv(YL, YR, KL, KR) \ -{ \ - (YL) = ((YR) | (KR)) ^ (YL); \ - (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ -} - -#define SHIFT_AND_PLACE(INDEX, OFFSET) \ -{ \ - TK[0] = KC[(OFFSET) * 4 + 0]; \ - TK[1] = KC[(OFFSET) * 4 + 1]; \ - TK[2] = KC[(OFFSET) * 4 + 2]; \ - TK[3] = KC[(OFFSET) * 4 + 3]; \ - \ - for( i = 1; i <= 4; i++ ) \ - if( shifts[(INDEX)][(OFFSET)][i -1] ) \ - ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ - \ - for( i = 0; i < 20; i++ ) \ - if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ - RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ - } \ -} - -static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], - uint32_t z[2]) -{ - uint32_t I0, I1; - I0 = x[0] ^ k[0]; - I1 = x[1] ^ k[1]; - - I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) | - ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) | - ((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) | - ((uint32_t) SBOX4((I0 ) & 0xFF) ); - I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) | - ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) | - ((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) | - ((uint32_t) SBOX1((I1 ) & 0xFF) ); - - I0 ^= (I1 << 8) | (I1 >> 24); - I1 ^= (I0 << 16) | (I0 >> 16); - I0 ^= (I1 >> 8) | (I1 << 24); - I1 ^= (I0 >> 8) | (I0 << 24); - - z[0] ^= I1; - z[1] ^= I0; -} - -void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); -} - -void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); -} - -/* - * Camellia key schedule (encryption) - */ -int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - int idx; - size_t i; - uint32_t *RK; - unsigned char t[64]; - uint32_t SIGMA[6][2]; - uint32_t KC[16]; - uint32_t TK[20]; - - RK = ctx->rk; - - memset( t, 0, 64 ); - memset( RK, 0, sizeof(ctx->rk) ); - - switch( keybits ) - { - case 128: ctx->nr = 3; idx = 0; break; - case 192: - case 256: ctx->nr = 4; idx = 1; break; - default : return( MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH ); - } - - for( i = 0; i < keybits / 8; ++i ) - t[i] = key[i]; - - if( keybits == 192 ) { - for( i = 0; i < 8; i++ ) - t[24 + i] = ~t[16 + i]; - } - - /* - * Prepare SIGMA values - */ - for( i = 0; i < 6; i++ ) { - GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); - GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); - } - - /* - * Key storage in KC - * Order: KL, KR, KA, KB - */ - memset( KC, 0, sizeof(KC) ); - - /* Store KL, KR */ - for( i = 0; i < 8; i++ ) - GET_UINT32_BE( KC[i], t, i * 4 ); - - /* Generate KA */ - for( i = 0; i < 4; ++i ) - KC[8 + i] = KC[i] ^ KC[4 + i]; - - camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); - camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); - - for( i = 0; i < 4; ++i ) - KC[8 + i] ^= KC[i]; - - camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); - camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); - - if( keybits > 128 ) { - /* Generate KB */ - for( i = 0; i < 4; ++i ) - KC[12 + i] = KC[4 + i] ^ KC[8 + i]; - - camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); - camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); - } - - /* - * Generating subkeys - */ - - /* Manipulating KL */ - SHIFT_AND_PLACE( idx, 0 ); - - /* Manipulating KR */ - if( keybits > 128 ) { - SHIFT_AND_PLACE( idx, 1 ); - } - - /* Manipulating KA */ - SHIFT_AND_PLACE( idx, 2 ); - - /* Manipulating KB */ - if( keybits > 128 ) { - SHIFT_AND_PLACE( idx, 3 ); - } - - /* Do transpositions */ - for( i = 0; i < 20; i++ ) { - if( transposes[idx][i] != -1 ) { - RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; - } - } - - return( 0 ); -} - -/* - * Camellia key schedule (decryption) - */ -int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - int idx, ret; - size_t i; - mbedtls_camellia_context cty; - uint32_t *RK; - uint32_t *SK; - - mbedtls_camellia_init( &cty ); - - /* Also checks keybits */ - if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) - goto exit; - - ctx->nr = cty.nr; - idx = ( ctx->nr == 4 ); - - RK = ctx->rk; - SK = cty.rk + 24 * 2 + 8 * idx * 2; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) - { - *RK++ = *SK++; - *RK++ = *SK++; - } - - SK -= 2; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - -exit: - mbedtls_camellia_free( &cty ); - - return( ret ); -} - -/* - * Camellia-ECB block encryption/decryption - */ -int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int NR; - uint32_t *RK, X[4]; - - ( (void) mode ); - - NR = ctx->nr; - RK = ctx->rk; - - GET_UINT32_BE( X[0], input, 0 ); - GET_UINT32_BE( X[1], input, 4 ); - GET_UINT32_BE( X[2], input, 8 ); - GET_UINT32_BE( X[3], input, 12 ); - - X[0] ^= *RK++; - X[1] ^= *RK++; - X[2] ^= *RK++; - X[3] ^= *RK++; - - while( NR ) { - --NR; - camellia_feistel( X, RK, X + 2 ); - RK += 2; - camellia_feistel( X + 2, RK, X ); - RK += 2; - camellia_feistel( X, RK, X + 2 ); - RK += 2; - camellia_feistel( X + 2, RK, X ); - RK += 2; - camellia_feistel( X, RK, X + 2 ); - RK += 2; - camellia_feistel( X + 2, RK, X ); - RK += 2; - - if( NR ) { - FL(X[0], X[1], RK[0], RK[1]); - RK += 2; - FLInv(X[2], X[3], RK[0], RK[1]); - RK += 2; - } - } - - X[2] ^= *RK++; - X[3] ^= *RK++; - X[0] ^= *RK++; - X[1] ^= *RK++; - - PUT_UINT32_BE( X[2], output, 0 ); - PUT_UINT32_BE( X[3], output, 4 ); - PUT_UINT32_BE( X[0], output, 8 ); - PUT_UINT32_BE( X[1], output, 12 ); - - return( 0 ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * Camellia-CBC buffer encryption/decryption - */ -int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[16]; - - if( length % 16 ) - return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_CAMELLIA_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 16 ); - mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * Camellia-CFB128 buffer encryption/decryption - */ -int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == MBEDTLS_CAMELLIA_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = ( n + 1 ) & 0x0F; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = ( n + 1 ) & 0x0F; - } - } - - *iv_off = n; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * Camellia-CTR buffer encryption/decryption - */ -int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, - stream_block ); - - for( i = 16; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = ( n + 1 ) & 0x0F; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ -#endif /* !MBEDTLS_CAMELLIA_ALT */ - -#if defined(MBEDTLS_SELF_TEST) - -/* - * Camellia test vectors from: - * - * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt - * (For each bitlength: Key 0, Nr 39) - */ -#define CAMELLIA_TESTS_ECB 2 - -static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = -{ - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, -}; - -static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = -{ - { - { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, - 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, - { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, - 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } - }, - { - { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, - 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, - { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, - 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } - }, - { - { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, - 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, - { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, - 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } - } -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#define CAMELLIA_TESTS_CBC 3 - -static const unsigned char camellia_test_cbc_key[3][32] = -{ - { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, - 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } - , - { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, - 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, - 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } - , - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } -}; - -static const unsigned char camellia_test_cbc_iv[16] = - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } -; - -static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = -{ - { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, - { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, - { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, - 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } - -}; - -static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = -{ - { - { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, - 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, - { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, - 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, - { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, - 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } - }, - { - { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, - 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, - { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, - 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, - { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, - 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } - }, - { - { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, - 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, - { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, - 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, - { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, - 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } - } -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * Camellia-CTR test vectors from: - * - * http://www.faqs.org/rfcs/rfc5528.html - */ - -static const unsigned char camellia_test_ctr_key[3][16] = -{ - { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, - 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, - { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, - 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, - { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, - 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } -}; - -static const unsigned char camellia_test_ctr_nonce_counter[3][16] = -{ - { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, - 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, - 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } -}; - -static const unsigned char camellia_test_ctr_pt[3][48] = -{ - { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, - 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23 } -}; - -static const unsigned char camellia_test_ctr_ct[3][48] = -{ - { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, - 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, - { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, - 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, - 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, - 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, - { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, - 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, - 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, - 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, - 0xDF, 0x50, 0x86, 0x96 } -}; - -static const int camellia_test_ctr_len[3] = - { 16, 32, 36 }; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -/* - * Checkup routine - */ -int mbedtls_camellia_self_test( int verbose ) -{ - int i, j, u, v; - unsigned char key[32]; - unsigned char buf[64]; - unsigned char src[16]; - unsigned char dst[16]; -#if defined(MBEDTLS_CIPHER_MODE_CBC) - unsigned char iv[16]; -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - size_t offset, len; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; -#endif - - mbedtls_camellia_context ctx; - - memset( key, 0, 32 ); - - for( j = 0; j < 6; j++ ) { - u = j >> 1; - v = j & 1; - - if( verbose != 0 ) - mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, - (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); - - for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { - memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) { - mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); - memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); - memcpy( dst, camellia_test_ecb_plain[i], 16 ); - } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ - mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); - memcpy( src, camellia_test_ecb_plain[i], 16 ); - memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); - } - - mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); - - if( memcmp( buf, dst, 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - /* - * CBC mode - */ - for( j = 0; j < 6; j++ ) - { - u = j >> 1; - v = j & 1; - - if( verbose != 0 ) - mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); - - memcpy( src, camellia_test_cbc_iv, 16 ); - memcpy( dst, camellia_test_cbc_iv, 16 ); - memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) { - mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); - } else { - mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); - } - - for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) { - memcpy( iv , src, 16 ); - memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); - memcpy( dst, camellia_test_cbc_plain[i], 16 ); - } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ - memcpy( iv , dst, 16 ); - memcpy( src, camellia_test_cbc_plain[i], 16 ); - memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); - } - - mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); - - if( memcmp( buf, dst, 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -#if defined(MBEDTLS_CIPHER_MODE_CTR) - /* - * CTR mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", - ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); - - memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); - memcpy( key, camellia_test_ctr_key[u], 16 ); - - offset = 0; - mbedtls_camellia_setkey_enc( &ctx, key, 128 ); - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) - { - len = camellia_test_ctr_len[u]; - memcpy( buf, camellia_test_ctr_ct[u], len ); - - mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - else - { - len = camellia_test_ctr_len[u]; - memcpy( buf, camellia_test_ctr_pt[u], len ); - - mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_CAMELLIA_C */ diff --git a/components/security/mbedtls/src/ccm.c b/components/security/mbedtls/src/ccm.c deleted file mode 100644 index 13a8fd1a..00000000 --- a/components/security/mbedtls/src/ccm.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * NIST SP800-38C compliant CCM implementation - * - * 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) - */ - -/* - * Definition of CCM: - * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf - * RFC 3610 "Counter with CBC-MAC (CCM)" - * - * Related: - * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CCM_C) - -#include "mbedtls/ccm.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -#define CCM_ENCRYPT 0 -#define CCM_DECRYPT 1 - -/* - * Initialize context - */ -void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); -} - -int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - - cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - if( cipher_info->block_size != 16 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - mbedtls_cipher_free( &ctx->cipher_ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} - -/* - * Free context - */ -void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) -{ - mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); -} - -/* - * Macros for common operations. - * Results in smaller compiled code than static inline functions. - */ - -/* - * Update the CBC-MAC state in y using a block in b - * (Always using b as the source helps the compiler optimise a bit better.) - */ -#define UPDATE_CBC_MAC \ - for( i = 0; i < 16; i++ ) \ - y[i] ^= b[i]; \ - \ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ - return( ret ); - -/* - * Encrypt or decrypt a partial block with CTR - * Warning: using b for temporary storage! src and dst must not be b! - * This avoids allocating one more 16 bytes buffer while allowing src == dst. - */ -#define CTR_CRYPT( dst, src, len ) \ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \ - return( ret ); \ - \ - for( i = 0; i < len; i++ ) \ - dst[i] = src[i] ^ b[i]; - -/* - * Authenticated encryption or decryption - */ -static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - unsigned char *tag, size_t tag_len ) -{ - int ret; - unsigned char i; - unsigned char q; - size_t len_left, olen; - unsigned char b[16]; - unsigned char y[16]; - unsigned char ctr[16]; - const unsigned char *src; - unsigned char *dst; - - /* - * Check length requirements: SP800-38C A.1 - * Additional requirement: a < 2^16 - 2^8 to simplify the code. - * 'length' checked later (when writing it to the first block) - */ - if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - /* Also implies q is within bounds */ - if( iv_len < 7 || iv_len > 13 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - if( add_len > 0xFF00 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - q = 16 - 1 - (unsigned char) iv_len; - - /* - * First block B_0: - * 0 .. 0 flags - * 1 .. iv_len nonce (aka iv) - * iv_len+1 .. 15 length - * - * With flags as (bits): - * 7 0 - * 6 add present? - * 5 .. 3 (t - 2) / 2 - * 2 .. 0 q - 1 - */ - b[0] = 0; - b[0] |= ( add_len > 0 ) << 6; - b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; - b[0] |= q - 1; - - memcpy( b + 1, iv, iv_len ); - - for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) - b[15-i] = (unsigned char)( len_left & 0xFF ); - - if( len_left > 0 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - - /* Start CBC-MAC with first block */ - memset( y, 0, 16 ); - UPDATE_CBC_MAC; - - /* - * If there is additional data, update CBC-MAC with - * add_len, add, 0 (padding to a block boundary) - */ - if( add_len > 0 ) - { - size_t use_len; - len_left = add_len; - src = add; - - memset( b, 0, 16 ); - b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); - b[1] = (unsigned char)( ( add_len ) & 0xFF ); - - use_len = len_left < 16 - 2 ? len_left : 16 - 2; - memcpy( b + 2, src, use_len ); - len_left -= use_len; - src += use_len; - - UPDATE_CBC_MAC; - - while( len_left > 0 ) - { - use_len = len_left > 16 ? 16 : len_left; - - memset( b, 0, 16 ); - memcpy( b, src, use_len ); - UPDATE_CBC_MAC; - - len_left -= use_len; - src += use_len; - } - } - - /* - * Prepare counter block for encryption: - * 0 .. 0 flags - * 1 .. iv_len nonce (aka iv) - * iv_len+1 .. 15 counter (initially 1) - * - * With flags as (bits): - * 7 .. 3 0 - * 2 .. 0 q - 1 - */ - ctr[0] = q - 1; - memcpy( ctr + 1, iv, iv_len ); - memset( ctr + 1 + iv_len, 0, q ); - ctr[15] = 1; - - /* - * Authenticate and {en,de}crypt the message. - * - * The only difference between encryption and decryption is - * the respective order of authentication and {en,de}cryption. - */ - len_left = length; - src = input; - dst = output; - - while( len_left > 0 ) - { - size_t use_len = len_left > 16 ? 16 : len_left; - - if( mode == CCM_ENCRYPT ) - { - memset( b, 0, 16 ); - memcpy( b, src, use_len ); - UPDATE_CBC_MAC; - } - - CTR_CRYPT( dst, src, use_len ); - - if( mode == CCM_DECRYPT ) - { - memset( b, 0, 16 ); - memcpy( b, dst, use_len ); - UPDATE_CBC_MAC; - } - - dst += use_len; - src += use_len; - len_left -= use_len; - - /* - * Increment counter. - * No need to check for overflow thanks to the length check above. - */ - for( i = 0; i < q; i++ ) - if( ++ctr[15-i] != 0 ) - break; - } - - /* - * Authentication: reset counter and crypt/mask internal tag - */ - for( i = 0; i < q; i++ ) - ctr[15-i] = 0; - - CTR_CRYPT( y, y, 16 ); - memcpy( tag, y, tag_len ); - - return( 0 ); -} - -/* - * Authenticated encryption - */ -int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - unsigned char *tag, size_t tag_len ) -{ - return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, - add, add_len, input, output, tag, tag_len ) ); -} - -/* - * Authenticated decryption - */ -int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - const unsigned char *tag, size_t tag_len ) -{ - int ret; - unsigned char check_tag[16]; - unsigned char i; - int diff; - - if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, - iv, iv_len, add, add_len, - input, output, check_tag, tag_len ) ) != 0 ) - { - return( ret ); - } - - /* Check tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) - { - mbedtls_zeroize( output, length ); - return( MBEDTLS_ERR_CCM_AUTH_FAILED ); - } - - return( 0 ); -} - - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -/* - * Examples 1 to 3 from SP800-38C Appendix C - */ - -#define NB_TESTS 3 - -/* - * The data is the same for all tests, only the used length changes - */ -static const unsigned char key[] = { - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f -}; - -static const unsigned char iv[] = { - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b -}; - -static const unsigned char ad[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 -}; - -static const unsigned char msg[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, -}; - -static const size_t iv_len [NB_TESTS] = { 7, 8, 12 }; -static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; -static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; -static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; - -static const unsigned char res[NB_TESTS][32] = { - { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, - { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, - 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, - 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, - { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, - 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, - 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, - 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } -}; - -int mbedtls_ccm_self_test( int verbose ) -{ - mbedtls_ccm_context ctx; - unsigned char out[32]; - size_t i; - int ret; - - mbedtls_ccm_init( &ctx ); - - if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( " CCM: setup failed" ); - - return( 1 ); - } - - for( i = 0; i < NB_TESTS; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); - - ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], - iv, iv_len[i], ad, add_len[i], - msg, out, - out + msg_len[i], tag_len[i] ); - - if( ret != 0 || - memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], - iv, iv_len[i], ad, add_len[i], - res[i], out, - res[i] + msg_len[i], tag_len[i] ); - - if( ret != 0 || - memcmp( out, msg, msg_len[i] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - mbedtls_ccm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -#endif /* MBEDTLS_CCM_C */ diff --git a/components/security/mbedtls/src/certs.c b/components/security/mbedtls/src/certs.c deleted file mode 100644 index ffe6bc98..00000000 --- a/components/security/mbedtls/src/certs.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * X.509 test certificates - * - * 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 - -#include "mbedtls/certs.h" - -#if defined(MBEDTLS_CERTS_C) - -#if defined(MBEDTLS_ECDSA_C) -#define TEST_CA_CRT_EC \ -"-----BEGIN CERTIFICATE-----\r\n" \ -"MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n" \ -"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ -"QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n" \ -"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ -"QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n" \ -"ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n" \ -"aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n" \ -"JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n" \ -"NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n" \ -"AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n" \ -"CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n" \ -"t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n" \ -"uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ -"-----END CERTIFICATE-----\r\n" -const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; - -const char mbedtls_test_ca_key_ec[] = -"-----BEGIN EC PRIVATE KEY-----\r\n" -"Proc-Type: 4,ENCRYPTED\r\n" -"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" -"\r\n" -"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" -"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" -"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" -"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" -"-----END EC PRIVATE KEY-----\r\n"; - -const char mbedtls_test_ca_pwd_ec[] = "PolarSSLTest"; - -const char mbedtls_test_srv_crt_ec[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" -"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" -"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" -"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" -"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" -"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" -"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" -"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" -"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" -"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" -"-----END CERTIFICATE-----\r\n"; - -const char mbedtls_test_srv_key_ec[] = -"-----BEGIN EC PRIVATE KEY-----\r\n" -"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" -"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" -"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" -"-----END EC PRIVATE KEY-----\r\n"; - -const char mbedtls_test_cli_crt_ec[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" -"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n" -"WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n" -"9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n" -"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n" -"IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n" -"CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n" -"lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" -"LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" -"-----END CERTIFICATE-----\r\n"; - -const char mbedtls_test_cli_key_ec[] = -"-----BEGIN EC PRIVATE KEY-----\r\n" -"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" -"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" -"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" -"-----END EC PRIVATE KEY-----\r\n"; - -const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); -const size_t mbedtls_test_ca_key_ec_len = sizeof( mbedtls_test_ca_key_ec ); -const size_t mbedtls_test_ca_pwd_ec_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; -const size_t mbedtls_test_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); -const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); -const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); -const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); -#else -#define TEST_CA_CRT_EC -#endif /* MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_RSA_C) -#define TEST_CA_CRT_RSA \ -"-----BEGIN CERTIFICATE-----\r\n" \ -"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ -"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ -"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ -"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ -"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ -"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ -"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ -"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ -"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ -"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" \ -"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" \ -"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" \ -"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" \ -"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" \ -"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" \ -"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" \ -"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ -"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ -"-----END CERTIFICATE-----\r\n" -const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; - -const char mbedtls_test_ca_key_rsa[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"Proc-Type: 4,ENCRYPTED\r\n" -"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" -"\r\n" -"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" -"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" -"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" -"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" -"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" -"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" -"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" -"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" -"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" -"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" -"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" -"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" -"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" -"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" -"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" -"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" -"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" -"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" -"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" -"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" -"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" -"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" -"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" -"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" -"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; - -const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; - -const char mbedtls_test_srv_crt_rsa[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" -"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" -"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" -"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" -"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" -"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" -"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" -"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" -"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" -"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" -"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" -"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" -"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" -"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" -"zhuYwjVuX6JHG0c=\r\n" -"-----END CERTIFICATE-----\r\n"; - -const char mbedtls_test_srv_key_rsa[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" -"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" -"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" -"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" -"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" -"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" -"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" -"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" -"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" -"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" -"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" -"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" -"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" -"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" -"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" -"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" -"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" -"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" -"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" -"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" -"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" -"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" -"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" -"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" -"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; - -const char mbedtls_test_cli_crt_rsa[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" -"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" -"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" -"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" -"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" -"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" -"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" -"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" -"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n" -"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n" -"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n" -"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n" -"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n" -"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n" -"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n" -"-----END CERTIFICATE-----\r\n"; - -const char mbedtls_test_cli_key_rsa[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" -"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" -"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" -"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" -"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" -"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" -"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" -"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" -"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" -"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" -"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" -"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" -"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" -"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" -"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" -"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" -"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" -"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" -"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" -"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" -"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" -"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" -"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" -"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" -"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; - -const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); -const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); -const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; -const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); -const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); -const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); -const size_t mbedtls_test_cli_key_rsa_len = sizeof( mbedtls_test_cli_key_rsa ); -#else -#define TEST_CA_CRT_RSA -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_PEM_PARSE_C) -/* Concatenation of all available CA certificates */ -const char mbedtls_test_cas_pem[] = TEST_CA_CRT_RSA TEST_CA_CRT_EC; -const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); -#endif - -/* List of all available CA certificates */ -const char * mbedtls_test_cas[] = { -#if defined(MBEDTLS_RSA_C) - mbedtls_test_ca_crt_rsa, -#endif -#if defined(MBEDTLS_ECDSA_C) - mbedtls_test_ca_crt_ec, -#endif - NULL -}; -const size_t mbedtls_test_cas_len[] = { -#if defined(MBEDTLS_RSA_C) - sizeof( mbedtls_test_ca_crt_rsa ), -#endif -#if defined(MBEDTLS_ECDSA_C) - sizeof( mbedtls_test_ca_crt_ec ), -#endif - 0 -}; - -#if defined(MBEDTLS_RSA_C) -const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; -const char *mbedtls_test_ca_key = mbedtls_test_ca_key_rsa; -const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_rsa; -const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_rsa; -const char *mbedtls_test_srv_key = mbedtls_test_srv_key_rsa; -const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_rsa; -const char *mbedtls_test_cli_key = mbedtls_test_cli_key_rsa; -const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_rsa ); -const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_rsa ); -const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; -const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_rsa ); -const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_rsa ); -const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_rsa ); -const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_rsa ); -#else /* ! MBEDTLS_RSA_C, so MBEDTLS_ECDSA_C */ -const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_ec; -const char *mbedtls_test_ca_key = mbedtls_test_ca_key_ec; -const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_ec; -const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_ec; -const char *mbedtls_test_srv_key = mbedtls_test_srv_key_ec; -const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_ec; -const char *mbedtls_test_cli_key = mbedtls_test_cli_key_ec; -const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_ec ); -const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_ec ); -const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; -const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_ec ); -const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_ec ); -const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_ec ); -const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_ec ); -#endif /* MBEDTLS_RSA_C */ - -#endif /* MBEDTLS_CERTS_C */ diff --git a/components/security/mbedtls/src/cipher.c b/components/security/mbedtls/src/cipher.c deleted file mode 100644 index 68baa0a5..00000000 --- a/components/security/mbedtls/src/cipher.c +++ /dev/null @@ -1,925 +0,0 @@ -/** - * \file cipher.c - * - * \brief Generic cipher wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * 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_CIPHER_C) - -#include "mbedtls/cipher.h" -#include "mbedtls/cipher_internal.h" - -#include -#include - -#if defined(MBEDTLS_AES_ALT) -#include "mbedtls/aes.h" -#endif - -#if defined(MBEDTLS_GCM_C) -#include "mbedtls/gcm.h" -#endif - -#if defined(MBEDTLS_CCM_C) -#include "mbedtls/ccm.h" -#endif - -#if defined(MBEDTLS_CMAC_C) -#include "mbedtls/cmac.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) -#define MBEDTLS_CIPHER_MODE_STREAM -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -static int supported_init = 0; - -const int *mbedtls_cipher_list( void ) -{ - const mbedtls_cipher_definition_t *def; - int *type; - - if( ! supported_init ) - { - def = mbedtls_cipher_definitions; - type = mbedtls_cipher_supported; - - while( def->type != 0 ) - *type++ = (*def++).type; - - *type = 0; - - supported_init = 1; - } - - return( mbedtls_cipher_supported ); -} - -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) -{ - const mbedtls_cipher_definition_t *def; - - for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) - if( def->type == cipher_type ) - return( def->info ); - - return( NULL ); -} - -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) -{ - const mbedtls_cipher_definition_t *def; - - if( NULL == cipher_name ) - return( NULL ); - - for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) - if( ! strcmp( def->info->name, cipher_name ) ) - return( def->info ); - - return( NULL ); -} - -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, - int key_bitlen, - const mbedtls_cipher_mode_t mode ) -{ - const mbedtls_cipher_definition_t *def; - - for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) - if( def->info->base->cipher == cipher_id && - def->info->key_bitlen == (unsigned) key_bitlen && - def->info->mode == mode ) - return( def->info ); - - return( NULL ); -} - -void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); -} - -void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) -{ - if( ctx == NULL ) - return; - -#if defined(MBEDTLS_CMAC_C) - if( ctx->cmac_ctx ) - { - mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); - mbedtls_free( ctx->cmac_ctx ); - } -#endif - - if( ctx->cipher_ctx ) - ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); - - mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); -} - -int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) -{ - if( NULL == cipher_info || NULL == ctx ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); - - if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) - return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); - - ctx->cipher_info = cipher_info; - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /* - * Ignore possible errors caused by a cipher mode that doesn't use padding - */ -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) - (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); -#else - (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); -#endif -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - - return( 0 ); -} - -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && - (int) ctx->cipher_info->key_bitlen != key_bitlen ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - ctx->key_bitlen = key_bitlen; - ctx->operation = operation; - - /* - * For CFB and CTR mode always use the encryption key schedule - */ - if( MBEDTLS_ENCRYPT == operation || - MBEDTLS_MODE_CFB == ctx->cipher_info->mode || - MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) - { - return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, - ctx->key_bitlen ); - } - - if( MBEDTLS_DECRYPT == operation ) - return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, - ctx->key_bitlen ); - - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); -} - -int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ) -{ - size_t actual_iv_size; - - if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - /* avoid buffer overflow in ctx->iv */ - if( iv_len > MBEDTLS_MAX_IV_LENGTH ) - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); - - if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) - actual_iv_size = iv_len; - else - { - actual_iv_size = ctx->cipher_info->iv_size; - - /* avoid reading past the end of input buffer */ - if( actual_iv_size > iv_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - memcpy( ctx->iv, iv, actual_iv_size ); - ctx->iv_size = actual_iv_size; - - return( 0 ); -} - -int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - ctx->unprocessed_len = 0; - -#if defined(MBEDTLS_AES_ALT) - ((mbedtls_aes_context *)(ctx->cipher_ctx))->status = AES_STATUS_INIT; -#endif - - return( 0 ); -} - -#if defined(MBEDTLS_GCM_C) -int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, - const unsigned char *ad, size_t ad_len ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - { - return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, - ctx->iv, ctx->iv_size, ad, ad_len ); - } - - return( 0 ); -} -#endif /* MBEDTLS_GCM_C */ - -int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen ) -{ - int ret; - size_t block_size = 0; - - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - *olen = 0; - block_size = mbedtls_cipher_get_block_size( ctx ); - - if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) - { - if( ilen != block_size ) - return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); - - *olen = ilen; - - if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, - ctx->operation, input, output ) ) ) - { - return( ret ); - } - - return( 0 ); - } - -#if defined(MBEDTLS_GCM_C) - if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) - { - *olen = ilen; - return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, - output ); - } -#endif - - if ( 0 == block_size ) - { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; - } - - if( input == output && - ( ctx->unprocessed_len != 0 || ilen % block_size ) ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) - { - size_t copy_len = 0; - - /* - * If there is not enough data for a full block, cache it. - */ - if( ( ctx->operation == MBEDTLS_DECRYPT && - ilen <= block_size - ctx->unprocessed_len ) || - ( ctx->operation == MBEDTLS_ENCRYPT && - ilen < block_size - ctx->unprocessed_len ) ) - { - memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, - ilen ); - - ctx->unprocessed_len += ilen; - return( 0 ); - } - - /* - * Process cached data first - */ - if( 0 != ctx->unprocessed_len ) - { - copy_len = block_size - ctx->unprocessed_len; - - memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, - copy_len ); - - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, block_size, ctx->iv, - ctx->unprocessed_data, output ) ) ) - { - return( ret ); - } - - *olen += block_size; - output += block_size; - ctx->unprocessed_len = 0; - - input += copy_len; - ilen -= copy_len; - } - - /* - * Cache final, incomplete block - */ - if( 0 != ilen ) - { - if( 0 == block_size ) - { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; - } - - copy_len = ilen % block_size; - if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) - copy_len = block_size; - - memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), - copy_len ); - - ctx->unprocessed_len += copy_len; - ilen -= copy_len; - } - - /* - * Process remaining full blocks - */ - if( ilen ) - { - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, ilen, ctx->iv, input, output ) ) ) - { - return( ret ); - } - - *olen += ilen; - } - - return( 0 ); - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) - if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) - { - if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, - ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, - input, output ) ) ) - { - return( ret ); - } - - *olen = ilen; - - return( 0 ); - } -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) - if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) - { - if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, - ilen, &ctx->unprocessed_len, ctx->iv, - ctx->unprocessed_data, input, output ) ) ) - { - return( ret ); - } - - *olen = ilen; - - return( 0 ); - } -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) - { - if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, - ilen, input, output ) ) ) - { - return( ret ); - } - - *olen = ilen; - - return( 0 ); - } -#endif /* MBEDTLS_CIPHER_MODE_STREAM */ - - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); -} - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) -/* - * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len - */ -static void add_pkcs_padding( unsigned char *output, size_t output_len, - size_t data_len ) -{ - size_t padding_len = output_len - data_len; - unsigned char i; - - for( i = 0; i < padding_len; i++ ) - output[data_len + i] = (unsigned char) padding_len; -} - -static int get_pkcs_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - size_t i, pad_idx; - unsigned char padding_len, bad = 0; - - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - padding_len = input[input_len - 1]; - *data_len = input_len - padding_len; - - /* Avoid logical || since it results in a branch */ - bad |= padding_len > input_len; - bad |= padding_len == 0; - - /* The number of bytes checked must be independent of padding_len, - * so pick input_len, which is usually 8 or 16 (one block) */ - pad_idx = input_len - padding_len; - for( i = 0; i < input_len; i++ ) - bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); - - return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); -} -#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ - -#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) -/* - * One and zeros padding: fill with 80 00 ... 00 - */ -static void add_one_and_zeros_padding( unsigned char *output, - size_t output_len, size_t data_len ) -{ - size_t padding_len = output_len - data_len; - unsigned char i = 0; - - output[data_len] = 0x80; - for( i = 1; i < padding_len; i++ ) - output[data_len + i] = 0x00; -} - -static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - size_t i; - unsigned char done = 0, prev_done, bad; - - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - bad = 0xFF; - *data_len = 0; - for( i = input_len; i > 0; i-- ) - { - prev_done = done; - done |= ( input[i-1] != 0 ); - *data_len |= ( i - 1 ) * ( done != prev_done ); - bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done ); - } - - return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); - -} -#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ - -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) -/* - * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length - */ -static void add_zeros_and_len_padding( unsigned char *output, - size_t output_len, size_t data_len ) -{ - size_t padding_len = output_len - data_len; - unsigned char i = 0; - - for( i = 1; i < padding_len; i++ ) - output[data_len + i - 1] = 0x00; - output[output_len - 1] = (unsigned char) padding_len; -} - -static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - size_t i, pad_idx; - unsigned char padding_len, bad = 0; - - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - padding_len = input[input_len - 1]; - *data_len = input_len - padding_len; - - /* Avoid logical || since it results in a branch */ - bad |= padding_len > input_len; - bad |= padding_len == 0; - - /* The number of bytes checked must be independent of padding_len */ - pad_idx = input_len - padding_len; - for( i = 0; i < input_len - 1; i++ ) - bad |= input[i] * ( i >= pad_idx ); - - return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); -} -#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ - -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) -/* - * Zero padding: fill with 00 ... 00 - */ -static void add_zeros_padding( unsigned char *output, - size_t output_len, size_t data_len ) -{ - size_t i; - - for( i = data_len; i < output_len; i++ ) - output[i] = 0x00; -} - -static int get_zeros_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - size_t i; - unsigned char done = 0, prev_done; - - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - *data_len = 0; - for( i = input_len; i > 0; i-- ) - { - prev_done = done; - done |= ( input[i-1] != 0 ); - *data_len |= i * ( done != prev_done ); - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ - -/* - * No padding: don't pad :) - * - * There is no add_padding function (check for NULL in mbedtls_cipher_finish) - * but a trivial get_padding function - */ -static int get_no_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - *data_len = input_len; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - -int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output, size_t *olen ) -{ - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - *olen = 0; - - if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || - MBEDTLS_MODE_CTR == ctx->cipher_info->mode || - MBEDTLS_MODE_GCM == ctx->cipher_info->mode || - MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) - { - return( 0 ); - } - - if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) - { - if( ctx->unprocessed_len != 0 ) - return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); - - return( 0 ); - } - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) - { - int ret = 0; - - if( MBEDTLS_ENCRYPT == ctx->operation ) - { - /* check for 'no padding' mode */ - if( NULL == ctx->add_padding ) - { - if( 0 != ctx->unprocessed_len ) - return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); - - return( 0 ); - } - - ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), - ctx->unprocessed_len ); - } - else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) - { - /* - * For decrypt operations, expect a full block, - * or an empty block if no padding - */ - if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) - return( 0 ); - - return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); - } - - /* cipher block */ - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, - ctx->unprocessed_data, output ) ) ) - { - return( ret ); - } - - /* Set output size for decryption */ - if( MBEDTLS_DECRYPT == ctx->operation ) - return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), - olen ); - - /* Set output size for encryption */ - *olen = mbedtls_cipher_get_block_size( ctx ); - return( 0 ); - } -#else - ((void) output); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); -} - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) -{ - if( NULL == ctx || - MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - switch( mode ) - { -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) - case MBEDTLS_PADDING_PKCS7: - ctx->add_padding = add_pkcs_padding; - ctx->get_padding = get_pkcs_padding; - break; -#endif -#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) - case MBEDTLS_PADDING_ONE_AND_ZEROS: - ctx->add_padding = add_one_and_zeros_padding; - ctx->get_padding = get_one_and_zeros_padding; - break; -#endif -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) - case MBEDTLS_PADDING_ZEROS_AND_LEN: - ctx->add_padding = add_zeros_and_len_padding; - ctx->get_padding = get_zeros_and_len_padding; - break; -#endif -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) - case MBEDTLS_PADDING_ZEROS: - ctx->add_padding = add_zeros_padding; - ctx->get_padding = get_zeros_padding; - break; -#endif - case MBEDTLS_PADDING_NONE: - ctx->add_padding = NULL; - ctx->get_padding = get_no_padding; - break; - - default: - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - -#if defined(MBEDTLS_GCM_C) -int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, - unsigned char *tag, size_t tag_len ) -{ - if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( MBEDTLS_ENCRYPT != ctx->operation ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); - - return( 0 ); -} - -int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, - const unsigned char *tag, size_t tag_len ) -{ - int ret; - - if( NULL == ctx || NULL == ctx->cipher_info || - MBEDTLS_DECRYPT != ctx->operation ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - { - unsigned char check_tag[16]; - size_t i; - int diff; - - if( tag_len > sizeof( check_tag ) ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, - check_tag, tag_len ) ) ) - { - return( ret ); - } - - /* Check the tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) - return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); - - return( 0 ); - } - - return( 0 ); -} -#endif /* MBEDTLS_GCM_C */ - -/* - * Packet-oriented wrapper for non-AEAD modes - */ -int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen ) -{ - int ret; - size_t finish_olen; - - if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) - return( ret ); - - *olen += finish_olen; - - return( 0 ); -} - -#if defined(MBEDTLS_CIPHER_MODE_AEAD) -/* - * Packet-oriented encryption for AEAD modes - */ -int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len ) -{ -#if defined(MBEDTLS_GCM_C) - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - { - *olen = ilen; - return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, - iv, iv_len, ad, ad_len, input, output, - tag_len, tag ) ); - } -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_CCM_C) - if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) - { - *olen = ilen; - return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, - iv, iv_len, ad, ad_len, input, output, - tag, tag_len ) ); - } -#endif /* MBEDTLS_CCM_C */ - - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); -} - -/* - * Packet-oriented decryption for AEAD modes - */ -int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - const unsigned char *tag, size_t tag_len ) -{ -#if defined(MBEDTLS_GCM_C) - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - { - int ret; - - *olen = ilen; - ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, - iv, iv_len, ad, ad_len, - tag, tag_len, input, output ); - - if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) - ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; - - return( ret ); - } -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_CCM_C) - if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) - { - int ret; - - *olen = ilen; - ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, - iv, iv_len, ad, ad_len, - input, output, tag, tag_len ); - - if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) - ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; - - return( ret ); - } -#endif /* MBEDTLS_CCM_C */ - - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); -} -#endif /* MBEDTLS_CIPHER_MODE_AEAD */ - -#endif /* MBEDTLS_CIPHER_C */ diff --git a/components/security/mbedtls/src/cipher_wrap.c b/components/security/mbedtls/src/cipher_wrap.c deleted file mode 100644 index 0315f20b..00000000 --- a/components/security/mbedtls/src/cipher_wrap.c +++ /dev/null @@ -1,1500 +0,0 @@ -/** - * \file cipher_wrap.c - * - * \brief Generic cipher wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * 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_CIPHER_C) - -#include "mbedtls/cipher_internal.h" - -#if defined(MBEDTLS_AES_C) -#include "mbedtls/aes.h" -#endif - -#if defined(MBEDTLS_ARC4_C) -#include "mbedtls/arc4.h" -#endif - -#if defined(MBEDTLS_CAMELLIA_C) -#include "mbedtls/camellia.h" -#endif - -#if defined(MBEDTLS_DES_C) -#include "mbedtls/des.h" -#endif - -#if defined(MBEDTLS_BLOWFISH_C) -#include "mbedtls/blowfish.h" -#endif - -#if defined(MBEDTLS_GCM_C) -#include "mbedtls/gcm.h" -#endif - -#if defined(MBEDTLS_CCM_C) -#include "mbedtls/ccm.h" -#endif - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#include -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_GCM_C) -/* shared by all GCM ciphers */ -static void *gcm_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); - - if( ctx != NULL ) - mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); - - return( ctx ); -} - -static void gcm_ctx_free( void *ctx ) -{ - mbedtls_gcm_free( ctx ); - mbedtls_free( ctx ); -} -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CCM_C) -/* shared by all CCM ciphers */ -static void *ccm_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); - - if( ctx != NULL ) - mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); - - return( ctx ); -} - -static void ccm_ctx_free( void *ctx ) -{ - mbedtls_ccm_free( ctx ); - mbedtls_free( ctx ); -} -#endif /* MBEDTLS_CCM_C */ - -#if defined(MBEDTLS_AES_C) - -#if !defined(MBEDTLS_AES_ALT) -static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, - output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, size_t *iv_off, unsigned char *iv, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, - input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, - stream_block, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); -} - -static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); -} - -static void * aes_ctx_alloc( void ) -{ - mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); - - if( aes == NULL ) - return( NULL ); - - mbedtls_aes_init( aes ); - - return( aes ); -} - -static void aes_ctx_free( void *ctx ) -{ - mbedtls_aes_free( (mbedtls_aes_context *) ctx ); - mbedtls_free( ctx ); -} - -#else /* MBEDTLS_AES_ALT */ - -static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_ecb_alt( (mbedtls_aes_context *) ctx, operation, input, output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_cbc_alt( (mbedtls_aes_context *) ctx, operation, length, iv, input, - output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_aes_setkey_dec_alt( (mbedtls_aes_context *) ctx, key, key_bitlen ); -} - -static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_aes_setkey_enc_alt( (mbedtls_aes_context *) ctx, key, key_bitlen ); -} - -static void* aes_ctx_alloc( void ) -{ - mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); - - if( aes == NULL ) - return( NULL ); - - mbedtls_aes_init_alt( aes ); - - return( aes ); -} - -static void aes_ctx_free( void *ctx ) -{ - mbedtls_aes_free_alt( (mbedtls_aes_context *) ctx ); - mbedtls_free( ctx ); -} -#endif /* MBEDTLS_AES_ALT */ - -static const mbedtls_cipher_base_t aes_info = { - MBEDTLS_CIPHER_ID_AES, - aes_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - aes_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - aes_crypt_cfb128_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - aes_crypt_ctr_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - aes_setkey_enc_wrap, - aes_setkey_dec_wrap, - aes_ctx_alloc, - aes_ctx_free -}; - -static const mbedtls_cipher_info_t aes_128_ecb_info = { - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_MODE_ECB, - 128, - "AES-128-ECB", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_192_ecb_info = { - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_MODE_ECB, - 192, - "AES-192-ECB", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_256_ecb_info = { - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_MODE_ECB, - 256, - "AES-256-ECB", - 16, - 0, - 16, - &aes_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t aes_128_cbc_info = { - MBEDTLS_CIPHER_AES_128_CBC, - MBEDTLS_MODE_CBC, - 128, - "AES-128-CBC", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_192_cbc_info = { - MBEDTLS_CIPHER_AES_192_CBC, - MBEDTLS_MODE_CBC, - 192, - "AES-192-CBC", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_256_cbc_info = { - MBEDTLS_CIPHER_AES_256_CBC, - MBEDTLS_MODE_CBC, - 256, - "AES-256-CBC", - 16, - 0, - 16, - &aes_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static const mbedtls_cipher_info_t aes_128_cfb128_info = { - MBEDTLS_CIPHER_AES_128_CFB128, - MBEDTLS_MODE_CFB, - 128, - "AES-128-CFB128", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_192_cfb128_info = { - MBEDTLS_CIPHER_AES_192_CFB128, - MBEDTLS_MODE_CFB, - 192, - "AES-192-CFB128", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_256_cfb128_info = { - MBEDTLS_CIPHER_AES_256_CFB128, - MBEDTLS_MODE_CFB, - 256, - "AES-256-CFB128", - 16, - 0, - 16, - &aes_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t aes_128_ctr_info = { - MBEDTLS_CIPHER_AES_128_CTR, - MBEDTLS_MODE_CTR, - 128, - "AES-128-CTR", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_192_ctr_info = { - MBEDTLS_CIPHER_AES_192_CTR, - MBEDTLS_MODE_CTR, - 192, - "AES-192-CTR", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_256_ctr_info = { - MBEDTLS_CIPHER_AES_256_CTR, - MBEDTLS_MODE_CTR, - 256, - "AES-256-CTR", - 16, - 0, - 16, - &aes_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#if defined(MBEDTLS_GCM_C) -static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, - key, key_bitlen ); -} - -static const mbedtls_cipher_base_t gcm_aes_info = { - MBEDTLS_CIPHER_ID_AES, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - gcm_aes_setkey_wrap, - gcm_aes_setkey_wrap, - gcm_ctx_alloc, - gcm_ctx_free, -}; - -static const mbedtls_cipher_info_t aes_128_gcm_info = { - MBEDTLS_CIPHER_AES_128_GCM, - MBEDTLS_MODE_GCM, - 128, - "AES-128-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_aes_info -}; - -static const mbedtls_cipher_info_t aes_192_gcm_info = { - MBEDTLS_CIPHER_AES_192_GCM, - MBEDTLS_MODE_GCM, - 192, - "AES-192-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_aes_info -}; - -static const mbedtls_cipher_info_t aes_256_gcm_info = { - MBEDTLS_CIPHER_AES_256_GCM, - MBEDTLS_MODE_GCM, - 256, - "AES-256-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_aes_info -}; -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CCM_C) -static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, - key, key_bitlen ); -} - -static const mbedtls_cipher_base_t ccm_aes_info = { - MBEDTLS_CIPHER_ID_AES, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - ccm_aes_setkey_wrap, - ccm_aes_setkey_wrap, - ccm_ctx_alloc, - ccm_ctx_free, -}; - -static const mbedtls_cipher_info_t aes_128_ccm_info = { - MBEDTLS_CIPHER_AES_128_CCM, - MBEDTLS_MODE_CCM, - 128, - "AES-128-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_aes_info -}; - -static const mbedtls_cipher_info_t aes_192_ccm_info = { - MBEDTLS_CIPHER_AES_192_CCM, - MBEDTLS_MODE_CCM, - 192, - "AES-192-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_aes_info -}; - -static const mbedtls_cipher_info_t aes_256_ccm_info = { - MBEDTLS_CIPHER_AES_256_CCM, - MBEDTLS_MODE_CCM, - 256, - "AES-256-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_aes_info -}; -#endif /* MBEDTLS_CCM_C */ - -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) - -static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, - output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, unsigned char *iv, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, - input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, size_t *iv_off, unsigned char *iv, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, - iv_off, iv, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, - nonce_counter, stream_block, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); -} - -static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); -} - -static void * camellia_ctx_alloc( void ) -{ - mbedtls_camellia_context *ctx; - ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); - - if( ctx == NULL ) - return( NULL ); - - mbedtls_camellia_init( ctx ); - - return( ctx ); -} - -static void camellia_ctx_free( void *ctx ) -{ - mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t camellia_info = { - MBEDTLS_CIPHER_ID_CAMELLIA, - camellia_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - camellia_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - camellia_crypt_cfb128_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - camellia_crypt_ctr_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - camellia_setkey_enc_wrap, - camellia_setkey_dec_wrap, - camellia_ctx_alloc, - camellia_ctx_free -}; - -static const mbedtls_cipher_info_t camellia_128_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_128_ECB, - MBEDTLS_MODE_ECB, - 128, - "CAMELLIA-128-ECB", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_192_ECB, - MBEDTLS_MODE_ECB, - 192, - "CAMELLIA-192-ECB", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_256_ECB, - MBEDTLS_MODE_ECB, - 256, - "CAMELLIA-256-ECB", - 16, - 0, - 16, - &camellia_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t camellia_128_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CBC, - MBEDTLS_MODE_CBC, - 128, - "CAMELLIA-128-CBC", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CBC, - MBEDTLS_MODE_CBC, - 192, - "CAMELLIA-192-CBC", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CBC, - MBEDTLS_MODE_CBC, - 256, - "CAMELLIA-256-CBC", - 16, - 0, - 16, - &camellia_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static const mbedtls_cipher_info_t camellia_128_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CFB128, - MBEDTLS_MODE_CFB, - 128, - "CAMELLIA-128-CFB128", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CFB128, - MBEDTLS_MODE_CFB, - 192, - "CAMELLIA-192-CFB128", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CFB128, - MBEDTLS_MODE_CFB, - 256, - "CAMELLIA-256-CFB128", - 16, - 0, - 16, - &camellia_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t camellia_128_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CTR, - MBEDTLS_MODE_CTR, - 128, - "CAMELLIA-128-CTR", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CTR, - MBEDTLS_MODE_CTR, - 192, - "CAMELLIA-192-CTR", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CTR, - MBEDTLS_MODE_CTR, - 256, - "CAMELLIA-256-CTR", - 16, - 0, - 16, - &camellia_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#if defined(MBEDTLS_GCM_C) -static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, - key, key_bitlen ); -} - -static const mbedtls_cipher_base_t gcm_camellia_info = { - MBEDTLS_CIPHER_ID_CAMELLIA, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - gcm_camellia_setkey_wrap, - gcm_camellia_setkey_wrap, - gcm_ctx_alloc, - gcm_ctx_free, -}; - -static const mbedtls_cipher_info_t camellia_128_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_128_GCM, - MBEDTLS_MODE_GCM, - 128, - "CAMELLIA-128-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_192_GCM, - MBEDTLS_MODE_GCM, - 192, - "CAMELLIA-192-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_256_GCM, - MBEDTLS_MODE_GCM, - 256, - "CAMELLIA-256-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_camellia_info -}; -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CCM_C) -static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, - key, key_bitlen ); -} - -static const mbedtls_cipher_base_t ccm_camellia_info = { - MBEDTLS_CIPHER_ID_CAMELLIA, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - ccm_camellia_setkey_wrap, - ccm_camellia_setkey_wrap, - ccm_ctx_alloc, - ccm_ctx_free, -}; - -static const mbedtls_cipher_info_t camellia_128_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CCM, - MBEDTLS_MODE_CCM, - 128, - "CAMELLIA-128-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CCM, - MBEDTLS_MODE_CCM, - 192, - "CAMELLIA-192-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CCM, - MBEDTLS_MODE_CCM, - 256, - "CAMELLIA-256-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_camellia_info -}; -#endif /* MBEDTLS_CCM_C */ - -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) - -static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - ((void) operation); - return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); -} - -static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - ((void) operation); - return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, - output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, - output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); -} - -static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); -} - -static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); -} - -static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); -} - -static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); -} - -static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); -} - -static void * des_ctx_alloc( void ) -{ - mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); - - if( des == NULL ) - return( NULL ); - - mbedtls_des_init( des ); - - return( des ); -} - -static void des_ctx_free( void *ctx ) -{ - mbedtls_des_free( (mbedtls_des_context *) ctx ); - mbedtls_free( ctx ); -} - -static void * des3_ctx_alloc( void ) -{ - mbedtls_des3_context *des3; - des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); - - if( des3 == NULL ) - return( NULL ); - - mbedtls_des3_init( des3 ); - - return( des3 ); -} - -static void des3_ctx_free( void *ctx ) -{ - mbedtls_des3_free( (mbedtls_des3_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t des_info = { - MBEDTLS_CIPHER_ID_DES, - des_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - des_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - des_setkey_enc_wrap, - des_setkey_dec_wrap, - des_ctx_alloc, - des_ctx_free -}; - -static const mbedtls_cipher_info_t des_ecb_info = { - MBEDTLS_CIPHER_DES_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES, - "DES-ECB", - 8, - 0, - 8, - &des_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t des_cbc_info = { - MBEDTLS_CIPHER_DES_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES, - "DES-CBC", - 8, - 0, - 8, - &des_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -static const mbedtls_cipher_base_t des_ede_info = { - MBEDTLS_CIPHER_ID_DES, - des3_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - des3_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - des3_set2key_enc_wrap, - des3_set2key_dec_wrap, - des3_ctx_alloc, - des3_ctx_free -}; - -static const mbedtls_cipher_info_t des_ede_ecb_info = { - MBEDTLS_CIPHER_DES_EDE_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES_EDE, - "DES-EDE-ECB", - 8, - 0, - 8, - &des_ede_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t des_ede_cbc_info = { - MBEDTLS_CIPHER_DES_EDE_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES_EDE, - "DES-EDE-CBC", - 8, - 0, - 8, - &des_ede_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -static const mbedtls_cipher_base_t des_ede3_info = { - MBEDTLS_CIPHER_ID_3DES, - des3_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - des3_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - des3_set3key_enc_wrap, - des3_set3key_dec_wrap, - des3_ctx_alloc, - des3_ctx_free -}; - -static const mbedtls_cipher_info_t des_ede3_ecb_info = { - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES_EDE3, - "DES-EDE3-ECB", - 8, - 0, - 8, - &des_ede3_info -}; -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t des_ede3_cbc_info = { - MBEDTLS_CIPHER_DES_EDE3_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES_EDE3, - "DES-EDE3-CBC", - 8, - 0, - 8, - &des_ede3_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_BLOWFISH_C) - -static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, - output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, unsigned char *iv, const unsigned char *input, - unsigned char *output ) -{ - return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, - input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, size_t *iv_off, unsigned char *iv, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, - iv_off, iv, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, - nonce_counter, stream_block, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); -} - -static void * blowfish_ctx_alloc( void ) -{ - mbedtls_blowfish_context *ctx; - ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); - - if( ctx == NULL ) - return( NULL ); - - mbedtls_blowfish_init( ctx ); - - return( ctx ); -} - -static void blowfish_ctx_free( void *ctx ) -{ - mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t blowfish_info = { - MBEDTLS_CIPHER_ID_BLOWFISH, - blowfish_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - blowfish_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - blowfish_crypt_cfb64_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - blowfish_crypt_ctr_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - blowfish_setkey_wrap, - blowfish_setkey_wrap, - blowfish_ctx_alloc, - blowfish_ctx_free -}; - -static const mbedtls_cipher_info_t blowfish_ecb_info = { - MBEDTLS_CIPHER_BLOWFISH_ECB, - MBEDTLS_MODE_ECB, - 128, - "BLOWFISH-ECB", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t blowfish_cbc_info = { - MBEDTLS_CIPHER_BLOWFISH_CBC, - MBEDTLS_MODE_CBC, - 128, - "BLOWFISH-CBC", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static const mbedtls_cipher_info_t blowfish_cfb64_info = { - MBEDTLS_CIPHER_BLOWFISH_CFB64, - MBEDTLS_MODE_CFB, - 128, - "BLOWFISH-CFB64", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t blowfish_ctr_info = { - MBEDTLS_CIPHER_BLOWFISH_CTR, - MBEDTLS_MODE_CTR, - 128, - "BLOWFISH-CTR", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ -#endif /* MBEDTLS_BLOWFISH_C */ - -#if defined(MBEDTLS_ARC4_C) -static int arc4_crypt_stream_wrap( void *ctx, size_t length, - const unsigned char *input, - unsigned char *output ) -{ - return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); -} - -static int arc4_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - /* we get key_bitlen in bits, arc4 expects it in bytes */ - if( key_bitlen % 8 != 0 ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); - return( 0 ); -} - -static void * arc4_ctx_alloc( void ) -{ - mbedtls_arc4_context *ctx; - ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); - - if( ctx == NULL ) - return( NULL ); - - mbedtls_arc4_init( ctx ); - - return( ctx ); -} - -static void arc4_ctx_free( void *ctx ) -{ - mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t arc4_base_info = { - MBEDTLS_CIPHER_ID_ARC4, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - arc4_crypt_stream_wrap, -#endif - arc4_setkey_wrap, - arc4_setkey_wrap, - arc4_ctx_alloc, - arc4_ctx_free -}; - -static const mbedtls_cipher_info_t arc4_128_info = { - MBEDTLS_CIPHER_ARC4_128, - MBEDTLS_MODE_STREAM, - 128, - "ARC4-128", - 0, - 0, - 1, - &arc4_base_info -}; -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -static int null_crypt_stream( void *ctx, size_t length, - const unsigned char *input, - unsigned char *output ) -{ - ((void) ctx); - memmove( output, input, length ); - return( 0 ); -} - -static int null_setkey( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) ctx); - ((void) key); - ((void) key_bitlen); - - return( 0 ); -} - -static void * null_ctx_alloc( void ) -{ - return( (void *) 1 ); -} - -static void null_ctx_free( void *ctx ) -{ - ((void) ctx); -} - -static const mbedtls_cipher_base_t null_base_info = { - MBEDTLS_CIPHER_ID_NULL, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - null_crypt_stream, -#endif - null_setkey, - null_setkey, - null_ctx_alloc, - null_ctx_free -}; - -static const mbedtls_cipher_info_t null_cipher_info = { - MBEDTLS_CIPHER_NULL, - MBEDTLS_MODE_STREAM, - 0, - "NULL", - 0, - 0, - 1, - &null_base_info -}; -#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ - -const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = -{ -#if defined(MBEDTLS_AES_C) - { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, - { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, - { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, - { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, - { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, - { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, - { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, - { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, - { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, -#endif -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, - { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, - { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, -#endif -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, - { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, - { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, -#endif -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_ARC4_C) - { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, -#endif - -#if defined(MBEDTLS_BLOWFISH_C) - { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, -#endif -#endif /* MBEDTLS_BLOWFISH_C */ - -#if defined(MBEDTLS_CAMELLIA_C) - { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, -#endif -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, -#endif -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, -#endif -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) - { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, - { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, - { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, - { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, - { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, -#endif -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) - { MBEDTLS_CIPHER_NULL, &null_cipher_info }, -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ - - { MBEDTLS_CIPHER_NONE, NULL } -}; - -#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] -int mbedtls_cipher_supported[NUM_CIPHERS]; - -#endif /* MBEDTLS_CIPHER_C */ diff --git a/components/security/mbedtls/src/cmac.c b/components/security/mbedtls/src/cmac.c deleted file mode 100644 index 035ad071..00000000 --- a/components/security/mbedtls/src/cmac.c +++ /dev/null @@ -1,1074 +0,0 @@ -/** - * \file cmac.c - * - * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES - * - * Copyright (C) 2006-2016, 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) - */ - -/* - * References: - * - * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The - * CMAC Mode for Authentication - * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf - * - * - RFC 4493 - The AES-CMAC Algorithm - * https://tools.ietf.org/html/rfc4493 - * - * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message - * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) - * Algorithm for the Internet Key Exchange Protocol (IKE) - * https://tools.ietf.org/html/rfc4615 - * - * Additional test vectors: ISO/IEC 9797-1 - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CMAC_C) - -#include "mbedtls/cmac.h" - -#include - - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#if defined(MBEDTLS_SELF_TEST) -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_SELF_TEST */ -#endif /* MBEDTLS_PLATFORM_C */ - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * Multiplication by u in the Galois field of GF(2^n) - * - * As explained in NIST SP 800-38B, this can be computed: - * - * If MSB(p) = 0, then p = (p << 1) - * If MSB(p) = 1, then p = (p << 1) ^ R_n - * with R_64 = 0x1B and R_128 = 0x87 - * - * Input and output MUST NOT point to the same buffer - * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. - */ -static int cmac_multiply_by_u( unsigned char *output, - const unsigned char *input, - size_t blocksize ) -{ - const unsigned char R_128 = 0x87; - const unsigned char R_64 = 0x1B; - unsigned char R_n, mask; - unsigned char overflow = 0x00; - int i; - - if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) - { - R_n = R_128; - } - else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) - { - R_n = R_64; - } - else - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - for( i = (int)blocksize - 1; i >= 0; i-- ) - { - output[i] = input[i] << 1 | overflow; - overflow = input[i] >> 7; - } - - /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 - * using bit operations to avoid branches */ - - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - mask = - ( input[0] >> 7 ); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - - output[ blocksize - 1 ] ^= R_n & mask; - - return( 0 ); -} - -/* - * Generate subkeys - * - * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm - */ -static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, - unsigned char* K1, unsigned char* K2 ) -{ - int ret; - unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; - size_t olen, block_size; - - mbedtls_zeroize( L, sizeof( L ) ); - - block_size = ctx->cipher_info->block_size; - - /* Calculate Ek(0) */ - if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) - goto exit; - - /* - * Generate K1 and K2 - */ - if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) - goto exit; - - if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) - goto exit; - -exit: - mbedtls_zeroize( L, sizeof( L ) ); - - return( ret ); -} - -static void cmac_xor_block( unsigned char *output, const unsigned char *input1, - const unsigned char *input2, - const size_t block_size ) -{ - size_t index; - - for( index = 0; index < block_size; index++ ) - output[ index ] = input1[ index ] ^ input2[ index ]; -} - -/* - * Create padded last block from (partial) last block. - * - * We can't use the padding option from the cipher layer, as it only works for - * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. - */ -static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], - size_t padded_block_len, - const unsigned char *last_block, - size_t last_block_len ) -{ - size_t j; - - for( j = 0; j < padded_block_len; j++ ) - { - if( j < last_block_len ) - padded_block[j] = last_block[j]; - else if( j == last_block_len ) - padded_block[j] = 0x80; - else - padded_block[j] = 0x00; - } -} - -int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, - const unsigned char *key, size_t keybits ) -{ - mbedtls_cipher_type_t type; - mbedtls_cmac_context_t *cmac_ctx; - int retval; - - if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - return( retval ); - - type = ctx->cipher_info->type; - - switch( type ) - { - case MBEDTLS_CIPHER_AES_128_ECB: - case MBEDTLS_CIPHER_AES_192_ECB: - case MBEDTLS_CIPHER_AES_256_ECB: - case MBEDTLS_CIPHER_DES_EDE3_ECB: - break; - default: - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - /* Allocated and initialise in the cipher context memory for the CMAC - * context */ - cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); - if( cmac_ctx == NULL ) - return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); - - ctx->cmac_ctx = cmac_ctx; - - mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); - - return 0; -} - -int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, - const unsigned char *input, size_t ilen ) -{ - mbedtls_cmac_context_t* cmac_ctx; - unsigned char *state; - int ret = 0; - size_t n, j, olen, block_size; - - if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || - ctx->cmac_ctx == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - cmac_ctx = ctx->cmac_ctx; - block_size = ctx->cipher_info->block_size; - state = ctx->cmac_ctx->state; - - /* Is there data still to process from the last call, that's greater in - * size than a block? */ - if( cmac_ctx->unprocessed_len > 0 && - ilen > block_size - cmac_ctx->unprocessed_len ) - { - memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], - input, - block_size - cmac_ctx->unprocessed_len ); - - cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); - - if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, - &olen ) ) != 0 ) - { - goto exit; - } - - input += block_size - cmac_ctx->unprocessed_len; - ilen -= block_size - cmac_ctx->unprocessed_len; - cmac_ctx->unprocessed_len = 0; - } - - /* n is the number of blocks including any final partial block */ - n = ( ilen + block_size - 1 ) / block_size; - - /* Iterate across the input data in block sized chunks, excluding any - * final partial or complete block */ - for( j = 1; j < n; j++ ) - { - cmac_xor_block( state, input, state, block_size ); - - if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, - &olen ) ) != 0 ) - goto exit; - - ilen -= block_size; - input += block_size; - } - - /* If there is data left over that wasn't aligned to a block */ - if( ilen > 0 ) - { - memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], - input, - ilen ); - cmac_ctx->unprocessed_len += ilen; - } - -exit: - return( ret ); -} - -int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output ) -{ - mbedtls_cmac_context_t* cmac_ctx; - unsigned char *state, *last_block; - unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; - int ret; - size_t olen, block_size; - - if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || - output == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - cmac_ctx = ctx->cmac_ctx; - block_size = ctx->cipher_info->block_size; - state = cmac_ctx->state; - - mbedtls_zeroize( K1, sizeof( K1 ) ); - mbedtls_zeroize( K2, sizeof( K2 ) ); - cmac_generate_subkeys( ctx, K1, K2 ); - - last_block = cmac_ctx->unprocessed_block; - - /* Calculate last block */ - if( cmac_ctx->unprocessed_len < block_size ) - { - cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); - cmac_xor_block( M_last, M_last, K2, block_size ); - } - else - { - /* Last block is complete block */ - cmac_xor_block( M_last, last_block, K1, block_size ); - } - - - cmac_xor_block( state, M_last, state, block_size ); - if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, - &olen ) ) != 0 ) - { - goto exit; - } - - memcpy( output, state, block_size ); - -exit: - /* Wipe the generated keys on the stack, and any other transients to avoid - * side channel leakage */ - mbedtls_zeroize( K1, sizeof( K1 ) ); - mbedtls_zeroize( K2, sizeof( K2 ) ); - - cmac_ctx->unprocessed_len = 0; - mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block ) ); - - mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); - return( ret ); -} - -int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) -{ - mbedtls_cmac_context_t* cmac_ctx; - - if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - cmac_ctx = ctx->cmac_ctx; - - /* Reset the internal state */ - cmac_ctx->unprocessed_len = 0; - mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block ) ); - mbedtls_zeroize( cmac_ctx->state, - sizeof( cmac_ctx->state ) ); - - return( 0 ); -} - -int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, - const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_cipher_context_t ctx; - int ret; - - if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - mbedtls_cipher_init( &ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) - goto exit; - - ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); - if( ret != 0 ) - goto exit; - - ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); - if( ret != 0 ) - goto exit; - - ret = mbedtls_cipher_cmac_finish( &ctx, output ); - -exit: - mbedtls_cipher_free( &ctx ); - - return( ret ); -} - -#if defined(MBEDTLS_AES_C) -/* - * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 - */ -int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, - const unsigned char *input, size_t in_len, - unsigned char *output ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; - unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; - - if( key == NULL || input == NULL || output == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); - if( cipher_info == NULL ) - { - /* Failing at this point must be due to a build issue */ - ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; - goto exit; - } - - if( key_length == MBEDTLS_AES_BLOCK_SIZE ) - { - /* Use key as is */ - memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); - } - else - { - memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); - - ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, - key_length, int_key ); - if( ret != 0 ) - goto exit; - } - - ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, - output ); - -exit: - mbedtls_zeroize( int_key, sizeof( int_key ) ); - - return( ret ); -} -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * CMAC test data for SP800-38B - * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf - * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf - * - * AES-CMAC-PRF-128 test data from RFC 4615 - * https://tools.ietf.org/html/rfc4615#page-4 - */ - -#define NB_CMAC_TESTS_PER_KEY 4 -#define NB_PRF_TESTS 3 - -#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) -/* All CMAC test inputs are truncated from the same 64 byte buffer. */ -static const unsigned char test_message[] = { - /* PT */ - 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 -}; -#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) -/* Truncation point of message for AES CMAC tests */ -static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { - /* Mlen */ - 0, - 16, - 20, - 64 -}; - -/* CMAC-AES128 Test Data */ -static const unsigned char aes_128_key[16] = { - 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c -}; -static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* K1 */ - 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, - 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde - }, - { - /* K2 */ - 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, - 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b - } -}; -static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* Example #1 */ - 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, - 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 - }, - { - /* Example #2 */ - 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, - 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c - }, - { - /* Example #3 */ - 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, - 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde - }, - { - /* Example #4 */ - 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, - 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe - } -}; - -/* CMAC-AES192 Test Data */ -static const unsigned char aes_192_key[24] = { - 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, - 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, - 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b -}; -static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* K1 */ - 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, - 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 - }, - { - /* K2 */ - 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, - 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c - } -}; -static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* Example #1 */ - 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, - 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 - }, - { - /* Example #2 */ - 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, - 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 - }, - { - /* Example #3 */ - 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, - 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 - }, - { - /* Example #4 */ - 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, - 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 - } -}; - -/* CMAC-AES256 Test Data */ -static const unsigned char aes_256_key[32] = { - 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, - 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, - 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, - 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 -}; -static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* K1 */ - 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, - 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f - }, - { - /* K2 */ - 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, - 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 - } -}; -static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* Example #1 */ - 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, - 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 - }, - { - /* Example #2 */ - 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, - 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c - }, - { - /* Example #3 */ - 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, - 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 - }, - { - /* Example #4 */ - 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, - 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 - } -}; -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_DES_C) -/* Truncation point of message for 3DES CMAC tests */ -static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { - 0, - 16, - 20, - 32 -}; - -/* CMAC-TDES (Generation) - 2 Key Test Data */ -static const unsigned char des3_2key_key[24] = { - /* Key1 */ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - /* Key2 */ - 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, - /* Key3 */ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef -}; -static const unsigned char des3_2key_subkeys[2][8] = { - { - /* K1 */ - 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 - }, - { - /* K2 */ - 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 - } -}; -static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { - { - /* Sample #1 */ - 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 - }, - { - /* Sample #2 */ - 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b - }, - { - /* Sample #3 */ - 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 - }, - { - /* Sample #4 */ - 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb - } -}; - -/* CMAC-TDES (Generation) - 3 Key Test Data */ -static const unsigned char des3_3key_key[24] = { - /* Key1 */ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, - /* Key2 */ - 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, - /* Key3 */ - 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 -}; -static const unsigned char des3_3key_subkeys[2][8] = { - { - /* K1 */ - 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 - }, - { - /* K2 */ - 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b - } -}; -static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { - { - /* Sample #1 */ - 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 - }, - { - /* Sample #2 */ - 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 - }, - { - /* Sample #3 */ - 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 - }, - { - /* Sample #4 */ - 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 - } -}; - -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) -/* AES AES-CMAC-PRF-128 Test Data */ -static const unsigned char PRFK[] = { - /* Key */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0xed, 0xcb -}; - -/* Sizes in bytes */ -static const size_t PRFKlen[NB_PRF_TESTS] = { - 18, - 16, - 10 -}; - -/* Message */ -static const unsigned char PRFM[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 -}; - -static const unsigned char PRFT[NB_PRF_TESTS][16] = { - { - 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, - 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a - }, - { - 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, - 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d - }, - { - 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, - 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d - } -}; -#endif /* MBEDTLS_AES_C */ - -static int cmac_test_subkeys( int verbose, - const char* testname, - const unsigned char* key, - int keybits, - const unsigned char* subkeys, - mbedtls_cipher_type_t cipher_type, - int block_size, - int num_tests ) -{ - int i, ret; - mbedtls_cipher_context_t ctx; - const mbedtls_cipher_info_t *cipher_info; - unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; - - cipher_info = mbedtls_cipher_info_from_type( cipher_type ); - if( cipher_info == NULL ) - { - /* Failing at this point must be due to a build issue */ - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); - } - - for( i = 0; i < num_tests; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); - - mbedtls_cipher_init( &ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "test execution failed\n" ); - - goto cleanup; - } - - if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "test execution failed\n" ); - - goto cleanup; - } - - ret = cmac_generate_subkeys( &ctx, K1, K2 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - goto cleanup; - } - - if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || - ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - mbedtls_cipher_free( &ctx ); - } - - goto exit; - -cleanup: - mbedtls_cipher_free( &ctx ); - -exit: - return( ret ); -} - -static int cmac_test_wth_cipher( int verbose, - const char* testname, - const unsigned char* key, - int keybits, - const unsigned char* messages, - const unsigned int message_lengths[4], - const unsigned char* expected_result, - mbedtls_cipher_type_t cipher_type, - int block_size, - int num_tests ) -{ - const mbedtls_cipher_info_t *cipher_info; - int i, ret; - unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; - - cipher_info = mbedtls_cipher_info_from_type( cipher_type ); - if( cipher_info == NULL ) - { - /* Failing at this point must be due to a build issue */ - ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; - goto exit; - } - - for( i = 0; i < num_tests; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); - - if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, - message_lengths[i], output ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - goto exit; - } - - if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - -exit: - return( ret ); -} - -#if defined(MBEDTLS_AES_C) -static int test_aes128_cmac_prf( int verbose ) -{ - int i; - int ret; - unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; - - for( i = 0; i < NB_PRF_TESTS; i++ ) - { - mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); - ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); - if( ret != 0 || - memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) - { - - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( ret ); - } - else if( verbose != 0 ) - { - mbedtls_printf( "passed\n" ); - } - } - return( ret ); -} -#endif /* MBEDTLS_AES_C */ - -int mbedtls_cmac_self_test( int verbose ) -{ - int ret; - -#if defined(MBEDTLS_AES_C) - /* AES-128 */ - if( ( ret = cmac_test_subkeys( verbose, - "AES 128", - aes_128_key, - 128, - (const unsigned char*)aes_128_subkeys, - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher( verbose, - "AES 128", - aes_128_key, - 128, - test_message, - aes_message_lengths, - (const unsigned char*)aes_128_expected_result, - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - /* AES-192 */ - if( ( ret = cmac_test_subkeys( verbose, - "AES 192", - aes_192_key, - 192, - (const unsigned char*)aes_192_subkeys, - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher( verbose, - "AES 192", - aes_192_key, - 192, - test_message, - aes_message_lengths, - (const unsigned char*)aes_192_expected_result, - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - /* AES-256 */ - if( ( ret = cmac_test_subkeys( verbose, - "AES 256", - aes_256_key, - 256, - (const unsigned char*)aes_256_subkeys, - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher ( verbose, - "AES 256", - aes_256_key, - 256, - test_message, - aes_message_lengths, - (const unsigned char*)aes_256_expected_result, - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_DES_C) - /* 3DES 2 key */ - if( ( ret = cmac_test_subkeys( verbose, - "3DES 2 key", - des3_2key_key, - 192, - (const unsigned char*)des3_2key_subkeys, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher( verbose, - "3DES 2 key", - des3_2key_key, - 192, - test_message, - des3_message_lengths, - (const unsigned char*)des3_2key_expected_result, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - /* 3DES 3 key */ - if( ( ret = cmac_test_subkeys( verbose, - "3DES 3 key", - des3_3key_key, - 192, - (const unsigned char*)des3_3key_subkeys, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher( verbose, - "3DES 3 key", - des3_3key_key, - 192, - test_message, - des3_message_lengths, - (const unsigned char*)des3_3key_expected_result, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) - if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) - return( ret ); -#endif /* MBEDTLS_AES_C */ - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_CMAC_C */ diff --git a/components/security/mbedtls/src/ctr_drbg.c b/components/security/mbedtls/src/ctr_drbg.c deleted file mode 100644 index dbb9aebb..00000000 --- a/components/security/mbedtls/src/ctr_drbg.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) - * - * 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) - */ -/* - * The NIST SP 800-90 DRBGs are described in the following publucation. - * - * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CTR_DRBG_C) -#include "mbedtls/ctr_drbg.h" - -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -/* 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; -} - -/* - * CTR_DRBG context initialization - */ -void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -/* - * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow - * NIST tests to succeed (which require known length fixed entropy) - */ -int mbedtls_ctr_drbg_seed_entropy_len( - mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len, - size_t entropy_len ) -{ - int ret; - unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; - - memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); - - mbedtls_aes_init( &ctx->aes_ctx ); - - ctx->f_entropy = f_entropy; - ctx->p_entropy = p_entropy; - - ctx->entropy_len = entropy_len; - ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; - - /* - * Initialize with an empty key - */ - mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); - - if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ) -{ - return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, - MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); -} - -void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) -{ - if( ctx == NULL ) - return; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - mbedtls_aes_free( &ctx->aes_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); -} - -void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) -{ - ctx->prediction_resistance = resistance; -} - -void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) -{ - ctx->entropy_len = len; -} - -void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) -{ - ctx->reseed_interval = interval; -} - -static int block_cipher_df( unsigned char *output, - const unsigned char *data, size_t data_len ) -{ - unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; - unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; - unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; - unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; - unsigned char *p, *iv; - mbedtls_aes_context aes_ctx; - - int i, j; - size_t buf_len, use_len; - - if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); - mbedtls_aes_init( &aes_ctx ); - - /* - * Construct IV (16 bytes) and S in buffer - * IV = Counter (in 32-bits) padded to 16 with zeroes - * S = Length input string (in 32-bits) || Length of output (in 32-bits) || - * data || 0x80 - * (Total is padded to a multiple of 16-bytes with zeroes) - */ - p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; - *p++ = ( data_len >> 24 ) & 0xff; - *p++ = ( data_len >> 16 ) & 0xff; - *p++ = ( data_len >> 8 ) & 0xff; - *p++ = ( data_len ) & 0xff; - p += 3; - *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; - memcpy( p, data, data_len ); - p[data_len] = 0x80; - - buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; - - for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) - key[i] = i; - - mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); - - /* - * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data - */ - for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) - { - p = buf; - memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - use_len = buf_len; - - while( use_len > 0 ) - { - for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) - chain[i] ^= p[i]; - p += MBEDTLS_CTR_DRBG_BLOCKSIZE; - use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? - MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; - - mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ); - } - - memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - - /* - * Update IV - */ - buf[3]++; - } - - /* - * Do final encryption with reduced data - */ - mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); - iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; - p = output; - - for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) - { - mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); - memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - p += MBEDTLS_CTR_DRBG_BLOCKSIZE; - } - - mbedtls_aes_free( &aes_ctx ); - - return( 0 ); -} - -static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, - const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) -{ - unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; - unsigned char *p = tmp; - int i, j; - - memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); - - for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) - { - /* - * Increase counter - */ - for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) - if( ++ctx->counter[i - 1] != 0 ) - break; - - /* - * Crypt counter block - */ - mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ); - - p += MBEDTLS_CTR_DRBG_BLOCKSIZE; - } - - for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) - tmp[i] ^= data[i]; - - /* - * Update key and counter - */ - mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); - memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - - return( 0 ); -} - -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) -{ - unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; - - if( add_len > 0 ) - { - /* MAX_INPUT would be more logical here, but we have to match - * block_cipher_df()'s limits since we can't propagate errors */ - if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) - add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; - - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); - } -} - -int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t len ) -{ - unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; - size_t seedlen = 0; - - if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || - len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); - - /* - * Gather entropy_len bytes of entropy to seed state - */ - if( 0 != ctx->f_entropy( ctx->p_entropy, seed, - ctx->entropy_len ) ) - { - return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); - } - - seedlen += ctx->entropy_len; - - /* - * Add additional data - */ - if( additional && len ) - { - memcpy( seed + seedlen, additional, len ); - seedlen += len; - } - - /* - * Reduce to 384 bits - */ - block_cipher_df( seed, seed, seedlen ); - - /* - * Update state - */ - ctr_drbg_update_internal( ctx, seed ); - ctx->reseed_counter = 1; - - return( 0 ); -} - -int mbedtls_ctr_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, size_t add_len ) -{ - int ret = 0; - mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; - unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; - unsigned char *p = output; - unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; - int i; - size_t use_len; - - if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) - return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); - - if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); - - if( ctx->reseed_counter > ctx->reseed_interval || - ctx->prediction_resistance ) - { - if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) - return( ret ); - - add_len = 0; - } - - if( add_len > 0 ) - { - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); - } - - while( output_len > 0 ) - { - /* - * Increase counter - */ - for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) - if( ++ctx->counter[i - 1] != 0 ) - break; - - /* - * Crypt counter block - */ - mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ); - - use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : - output_len; - /* - * Copy random block to destination - */ - memcpy( p, tmp, use_len ); - p += use_len; - output_len -= use_len; - } - - ctr_drbg_update_internal( ctx, add_input ); - - ctx->reseed_counter++; - - return( 0 ); -} - -int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) -{ - int ret; - mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -#if defined(MBEDTLS_FS_IO) -#if 0 -int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) -{ - int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; - FILE *f; - unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "wb" ) ) == NULL ) - return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); - - if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) - goto exit; - - if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) - { - ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; - goto exit; - } - - ret = 0; - -exit: - fclose( f ); - return( ret ); -} - -int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) -{ - FILE *f; - size_t n; - unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_CTR_DRBG_MAX_INPUT ) - { - fclose( f ); - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); - } - - if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); - } - - fclose( f ); - - mbedtls_ctr_drbg_update( ctx, buf, n ); - - return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); -} -#endif -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_SELF_TEST) - -static const unsigned char entropy_source_pr[96] = - { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, - 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, - 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, - 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, - 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, - 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, - 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, - 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, - 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, - 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, - 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, - 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; - -static const unsigned char entropy_source_nopr[64] = - { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, - 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, - 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, - 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, - 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, - 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, - 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, - 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; - -static const unsigned char nonce_pers_pr[16] = - { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, - 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; - -static const unsigned char nonce_pers_nopr[16] = - { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, - 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; - -static const unsigned char result_pr[16] = - { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, - 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; - -static const unsigned char result_nopr[16] = - { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, - 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; - -static size_t test_offset; -static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, - size_t len ) -{ - const unsigned char *p = data; - memcpy( buf, p + test_offset, len ); - test_offset += len; - return( 0 ); -} - -#define CHK( c ) if( (c) != 0 ) \ - { \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - return( 1 ); \ - } - -/* - * Checkup routine - */ -int mbedtls_ctr_drbg_self_test( int verbose ) -{ - mbedtls_ctr_drbg_context ctx; - unsigned char buf[16]; - - mbedtls_ctr_drbg_init( &ctx ); - - /* - * Based on a NIST CTR_DRBG test vector (PR = True) - */ - if( verbose != 0 ) - mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); - - test_offset = 0; - CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, - (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); - mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); - CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); - - mbedtls_ctr_drbg_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - /* - * Based on a NIST CTR_DRBG test vector (PR = FALSE) - */ - if( verbose != 0 ) - mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); - - mbedtls_ctr_drbg_init( &ctx ); - - test_offset = 0; - CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, - (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); - CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); - CHK( memcmp( buf, result_nopr, 16 ) ); - - mbedtls_ctr_drbg_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_CTR_DRBG_C */ diff --git a/components/security/mbedtls/src/debug.c b/components/security/mbedtls/src/debug.c deleted file mode 100644 index 78e3f89b..00000000 --- a/components/security/mbedtls/src/debug.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Debugging routines - * - * 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_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#define mbedtls_time_t time_t -#define mbedtls_snprintf snprintf -#endif - -#include "mbedtls/debug.h" - -#include -#include -#include - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#define DEBUG_BUF_SIZE 512 - -static int debug_threshold = 8; - -void mbedtls_debug_set_threshold( int threshold ) -{ - debug_threshold = threshold; -} - -#if defined(MBEDTLS_DEBUG_C) - -/* - * All calls to f_dbg must be made via this function - */ -static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *str ) -{ - /* - * If in a threaded environment, we need a thread identifier. - * Since there is no portable way to get one, use the address of the ssl - * context instead, as it shouldn't be shared between threads. - */ -#if defined(MBEDTLS_THREADING_C) - char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ - mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); - ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); -#else - ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); -#endif -} - -void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *format, ... ) -{ - va_list argp; - char str[DEBUG_BUF_SIZE]; - int ret; - - //printf("%p:%p:%p:%d\r\n", ssl, ssl->conf, ssl->conf->f_dbg, debug_threshold); - if( NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold ) - return; - - va_start( argp, format ); -#if defined(_WIN32) -#if defined(_TRUNCATE) - ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp ); -#else - ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); - if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE ) - { - str[DEBUG_BUF_SIZE-1] = '\0'; - ret = -1; - } -#endif -#else - ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); -#endif - va_end( argp ); - - if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) - { - str[ret] = '\n'; - str[ret + 1] = '\0'; - } - - debug_send_line( ssl, level, file, line, str ); -} - -void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret ) -{ - char str[DEBUG_BUF_SIZE]; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - /* - * With non-blocking I/O and examples that just retry immediately, - * the logs would be quickly flooded with WANT_READ, so ignore that. - * Don't ignore WANT_WRITE however, since is is usually rare. - */ - if( ret == MBEDTLS_ERR_SSL_WANT_READ ) - return; - - mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", - text, ret, -ret ); - - debug_send_line( ssl, level, file, line, str ); -} - -void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text, - const unsigned char *buf, size_t len ) -{ - char str[DEBUG_BUF_SIZE]; - char txt[17]; - size_t i, idx = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", - text, (unsigned int) len ); - - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - memset( txt, 0, sizeof( txt ) ); - for( i = 0; i < len; i++ ) - { - if( i >= 4096 ) - break; - - if( i % 16 == 0 ) - { - if( i > 0 ) - { - mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - memset( txt, 0, sizeof( txt ) ); - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", - (unsigned int) i ); - - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", - (unsigned int) buf[i] ); - txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; - } - - if( len > 0 ) - { - for( /* i = i */; i % 16 != 0; i++ ) - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); - debug_send_line( ssl, level, file, line, str ); - } -} - -#if defined(MBEDTLS_ECP_C) -void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_ecp_point *X ) -{ - char str[DEBUG_BUF_SIZE]; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); - mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); - - mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); - mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); -} -#endif /* MBEDTLS_ECP_C */ - -#if !defined(MBEDTLS_PK_ALT) -#if defined(MBEDTLS_BIGNUM_C) -void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_mpi *X ) -{ - char str[DEBUG_BUF_SIZE]; - int j, k, zeros = 1; - size_t i, n, idx = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold ) - return; - - for( n = X->n - 1; n > 0; n-- ) - if( X->p[n] != 0 ) - break; - - for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- ) - if( ( ( X->p[n] >> j ) & 1 ) != 0 ) - break; - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n", - text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) ); - - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - for( i = n + 1, j = 0; i > 0; i-- ) - { - if( zeros && X->p[i - 1] == 0 ) - continue; - - for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- ) - { - if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) - continue; - else - zeros = 0; - - if( j % 16 == 0 ) - { - if( j > 0 ) - { - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); - debug_send_line( ssl, level, file, line, str ); - idx = 0; - } - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int) - ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); - - j++; - } - - } - - if( zeros == 1 ) - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" ); - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); - debug_send_line( ssl, level, file, line, str ); -} -#endif /* MBEDTLS_BIGNUM_C */ -#endif /* MBEDTLS_PK_ALT */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_pk_context *pk ) -{ - size_t i; - mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; - char name[16]; - - memset( items, 0, sizeof( items ) ); - - if( mbedtls_pk_debug( pk, items ) != 0 ) - { - debug_send_line( ssl, level, file, line, - "invalid PK context\n" ); - return; - } - - for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) - { - if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) - return; - - mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); - name[sizeof( name ) - 1] = '\0'; - -#if !defined(MBEDTLS_PK_ALT) - if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) - mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); - else -#if defined(MBEDTLS_ECP_C) - if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) - mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); - else -#endif -#endif - debug_send_line( ssl, level, file, line, - "should not happen\n" ); - } -} - -static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text ) -{ - char str[DEBUG_BUF_SIZE]; - const char *start, *cur; - - start = text; - for( cur = text; *cur != '\0'; cur++ ) - { - if( *cur == '\n' ) - { - size_t len = cur - start + 1; - if( len > DEBUG_BUF_SIZE - 1 ) - len = DEBUG_BUF_SIZE - 1; - - memcpy( str, start, len ); - str[len] = '\0'; - - debug_send_line( ssl, level, file, line, str ); - - start = cur + 1; - } - } -} - -void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_x509_crt *crt ) -{ - char str[DEBUG_BUF_SIZE]; - int i = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold ) - return; - - while( crt != NULL ) - { - char buf[1024]; - - mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); - debug_send_line( ssl, level, file, line, str ); - - mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); - debug_print_line_by_line( ssl, level, file, line, buf ); - - debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); - - crt = crt->next; - } -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -void mbedtls_debug_print_data(int level, - const char *file, int line, - const char *name, const unsigned char *data, int len) -{ - int i; - - if (data == NULL || len == 0 || level > debug_threshold) { - return; - } - - printf("%s line: %d %s - len: %d\n", file, line, name , len); - - for (i = 0; i < len - len % 8; i += 8) { - printf("%s: %d - %s: %02x %02x %02x %02x %02x %02x %02x %02x\n", - file, line, name, - data[i+0], data[i+1], data[i+2], data[i+3], - data[i+4], data[i+5], data[i+6], data[i+7]); - } - while(i < len) { - printf("%s line: %d %s %02x\n", file, line, name, data[i++]); - } - -} - -#endif /* MBEDTLS_DEBUG_C */ diff --git a/components/security/mbedtls/src/des.c b/components/security/mbedtls/src/des.c deleted file mode 100644 index 09f95cfc..00000000 --- a/components/security/mbedtls/src/des.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * FIPS-46-3 compliant Triple-DES implementation - * - * 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) - */ -/* - * DES, on which TDES is based, was originally designed by Horst Feistel - * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). - * - * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_DES_C) - -#include "mbedtls/des.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_DES_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * Expanded DES S-boxes - */ -static const uint32_t SB1[64] = -{ - 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static const uint32_t SB2[64] = -{ - 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static const uint32_t SB3[64] = -{ - 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static const uint32_t SB4[64] = -{ - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static const uint32_t SB5[64] = -{ - 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static const uint32_t SB6[64] = -{ - 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static const uint32_t SB7[64] = -{ - 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static const uint32_t SB8[64] = -{ - 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - -/* - * PC1: left and right halves bit-swap - */ -static const uint32_t LHs[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const uint32_t RHs[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - -/* - * Initial Permutation macro - */ -#define DES_IP(X,Y) \ -{ \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ - X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ -} - -/* - * Final Permutation macro - */ -#define DES_FP(X,Y) \ -{ \ - X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ - Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ -} - -/* - * DES round macro - */ -#define DES_ROUND(X,Y) \ -{ \ - T = *SK++ ^ X; \ - Y ^= SB8[ (T ) & 0x3F ] ^ \ - SB6[ (T >> 8) & 0x3F ] ^ \ - SB4[ (T >> 16) & 0x3F ] ^ \ - SB2[ (T >> 24) & 0x3F ]; \ - \ - T = *SK++ ^ ((X << 28) | (X >> 4)); \ - Y ^= SB7[ (T ) & 0x3F ] ^ \ - SB5[ (T >> 8) & 0x3F ] ^ \ - SB3[ (T >> 16) & 0x3F ] ^ \ - SB1[ (T >> 24) & 0x3F ]; \ -} - -#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; } - -void mbedtls_des_init( mbedtls_des_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_des_context ) ); -} - -void mbedtls_des_free( mbedtls_des_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_des_context ) ); -} - -void mbedtls_des3_init( mbedtls_des3_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_des3_context ) ); -} - -void mbedtls_des3_free( mbedtls_des3_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_des3_context ) ); -} - -static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, - 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, - 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, - 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, - 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, - 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, - 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, - 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, - 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, - 254 }; - -void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) - key[i] = odd_parity_table[key[i] / 2]; -} - -/* - * Check the given key's parity, returns 1 on failure, 0 on SUCCESS - */ -int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) - if( key[i] != odd_parity_table[key[i] / 2] ) - return( 1 ); - - return( 0 ); -} - -/* - * Table of weak and semi-weak keys - * - * Source: http://en.wikipedia.org/wiki/Weak_key - * - * Weak: - * Alternating ones + zeros (0x0101010101010101) - * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) - * '0xE0E0E0E0F1F1F1F1' - * '0x1F1F1F1F0E0E0E0E' - * - * Semi-weak: - * 0x011F011F010E010E and 0x1F011F010E010E01 - * 0x01E001E001F101F1 and 0xE001E001F101F101 - * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 - * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E - * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E - * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 - * - */ - -#define WEAK_KEY_COUNT 16 - -static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = -{ - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, - { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, - { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, - - { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, - { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, - { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, - { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, - { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, - { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, - { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, - { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, - { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, - { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, - { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, - { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } -}; - -int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < WEAK_KEY_COUNT; i++ ) - if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) - return( 1 ); - - return( 0 ); -} - -#if !defined(MBEDTLS_DES_SETKEY_ALT) -void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - uint32_t X, Y, T; - - GET_UINT32_BE( X, key, 0 ); - GET_UINT32_BE( Y, key, 4 ); - - /* - * Permuted Choice 1 - */ - T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); - T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); - - X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) - | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) - | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) - | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); - - Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) - | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) - | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) - | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); - - X &= 0x0FFFFFFF; - Y &= 0x0FFFFFFF; - - /* - * calculate subkeys - */ - for( i = 0; i < 16; i++ ) - { - if( i < 2 || i == 8 || i == 15 ) - { - X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; - Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; - } - else - { - X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; - Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; - } - - *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) - | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) - | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) - | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) - | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) - | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) - | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) - | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) - | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) - | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) - | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); - - *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) - | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) - | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) - | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) - | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) - | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) - | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) - | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) - | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) - | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) - | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); - } -} -#endif /* !MBEDTLS_DES_SETKEY_ALT */ - -/* - * DES key schedule (56-bit, encryption) - */ -int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - mbedtls_des_setkey( ctx->sk, key ); - - return( 0 ); -} - -/* - * DES key schedule (56-bit, decryption) - */ -int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - - mbedtls_des_setkey( ctx->sk, key ); - - for( i = 0; i < 16; i += 2 ) - { - SWAP( ctx->sk[i ], ctx->sk[30 - i] ); - SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); - } - - return( 0 ); -} - -static void des3_set2key( uint32_t esk[96], - uint32_t dsk[96], - const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) -{ - int i; - - mbedtls_des_setkey( esk, key ); - mbedtls_des_setkey( dsk + 32, key + 8 ); - - for( i = 0; i < 32; i += 2 ) - { - dsk[i ] = esk[30 - i]; - dsk[i + 1] = esk[31 - i]; - - esk[i + 32] = dsk[62 - i]; - esk[i + 33] = dsk[63 - i]; - - esk[i + 64] = esk[i ]; - esk[i + 65] = esk[i + 1]; - - dsk[i + 64] = dsk[i ]; - dsk[i + 65] = dsk[i + 1]; - } -} - -/* - * Triple-DES key schedule (112-bit, encryption) - */ -int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) -{ - uint32_t sk[96]; - - des3_set2key( ctx->sk, sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); - - return( 0 ); -} - -/* - * Triple-DES key schedule (112-bit, decryption) - */ -int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) -{ - uint32_t sk[96]; - - des3_set2key( sk, ctx->sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); - - return( 0 ); -} - -static void des3_set3key( uint32_t esk[96], - uint32_t dsk[96], - const unsigned char key[24] ) -{ - int i; - - mbedtls_des_setkey( esk, key ); - mbedtls_des_setkey( dsk + 32, key + 8 ); - mbedtls_des_setkey( esk + 64, key + 16 ); - - for( i = 0; i < 32; i += 2 ) - { - dsk[i ] = esk[94 - i]; - dsk[i + 1] = esk[95 - i]; - - esk[i + 32] = dsk[62 - i]; - esk[i + 33] = dsk[63 - i]; - - dsk[i + 64] = esk[30 - i]; - dsk[i + 65] = esk[31 - i]; - } -} - -/* - * Triple-DES key schedule (168-bit, encryption) - */ -int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) -{ - uint32_t sk[96]; - - des3_set3key( ctx->sk, sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); - - return( 0 ); -} - -/* - * Triple-DES key schedule (168-bit, decryption) - */ -int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) -{ - uint32_t sk[96]; - - des3_set3key( sk, ctx->sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); - - return( 0 ); -} - -/* - * DES-ECB block encryption/decryption - */ -#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) -int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - uint32_t X, Y, T, *SK; - - SK = ctx->sk; - - GET_UINT32_BE( X, input, 0 ); - GET_UINT32_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_UINT32_BE( Y, output, 0 ); - PUT_UINT32_BE( X, output, 4 ); - - return( 0 ); -} -#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * DES-CBC buffer encryption/decryption - */ -int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_DES_ENCRYPT ) - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_des_crypt_ecb( ctx, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else /* MBEDTLS_DES_DECRYPT */ - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - mbedtls_des_crypt_ecb( ctx, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -/* - * 3DES-ECB block encryption/decryption - */ -#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) -int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - uint32_t X, Y, T, *SK; - - SK = ctx->sk; - - GET_UINT32_BE( X, input, 0 ); - GET_UINT32_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( X, Y ); - DES_ROUND( Y, X ); - } - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_UINT32_BE( Y, output, 0 ); - PUT_UINT32_BE( X, output, 4 ); - - return( 0 ); -} -#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * 3DES-CBC buffer encryption/decryption - */ -int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_DES_ENCRYPT ) - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_des3_crypt_ecb( ctx, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else /* MBEDTLS_DES_DECRYPT */ - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - mbedtls_des3_crypt_ecb( ctx, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#endif /* !MBEDTLS_DES_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * DES and 3DES test vectors from: - * - * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip - */ -static const unsigned char des3_test_keys[24] = -{ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, - 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 -}; - -static const unsigned char des3_test_buf[8] = -{ - 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 -}; - -static const unsigned char des3_test_ecb_dec[3][8] = -{ - { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, - { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, - { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } -}; - -static const unsigned char des3_test_ecb_enc[3][8] = -{ - { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, - { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, - { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const unsigned char des3_test_iv[8] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, -}; - -static const unsigned char des3_test_cbc_dec[3][8] = -{ - { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, - { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, - { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } -}; - -static const unsigned char des3_test_cbc_enc[3][8] = -{ - { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, - { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, - { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -/* - * Checkup routine - */ -int mbedtls_des_self_test( int verbose ) -{ - int i, j, u, v, ret = 0; - mbedtls_des_context ctx; - mbedtls_des3_context ctx3; - unsigned char buf[8]; -#if defined(MBEDTLS_CIPHER_MODE_CBC) - unsigned char prv[8]; - unsigned char iv[8]; -#endif - - mbedtls_des_init( &ctx ); - mbedtls_des3_init( &ctx3 ); - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " DES%c-ECB-%3d (%s): ", - ( u == 0 ) ? ' ' : '3', 56 + u * 56, - ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( buf, des3_test_buf, 8 ); - - switch( i ) - { - case 0: - mbedtls_des_setkey_dec( &ctx, des3_test_keys ); - break; - - case 1: - mbedtls_des_setkey_enc( &ctx, des3_test_keys ); - break; - - case 2: - mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); - break; - - case 3: - mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); - break; - - case 4: - mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); - break; - - case 5: - mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); - break; - - default: - return( 1 ); - } - - for( j = 0; j < 10000; j++ ) - { - if( u == 0 ) - mbedtls_des_crypt_ecb( &ctx, buf, buf ); - else - mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); - } - - if( ( v == MBEDTLS_DES_DECRYPT && - memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || - ( v != MBEDTLS_DES_DECRYPT && - memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " DES%c-CBC-%3d (%s): ", - ( u == 0 ) ? ' ' : '3', 56 + u * 56, - ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, des3_test_iv, 8 ); - memcpy( prv, des3_test_iv, 8 ); - memcpy( buf, des3_test_buf, 8 ); - - switch( i ) - { - case 0: - mbedtls_des_setkey_dec( &ctx, des3_test_keys ); - break; - - case 1: - mbedtls_des_setkey_enc( &ctx, des3_test_keys ); - break; - - case 2: - mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); - break; - - case 3: - mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); - break; - - case 4: - mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); - break; - - case 5: - mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); - break; - - default: - return( 1 ); - } - - if( v == MBEDTLS_DES_DECRYPT ) - { - for( j = 0; j < 10000; j++ ) - { - if( u == 0 ) - mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); - else - mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); - } - } - else - { - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[8]; - - if( u == 0 ) - mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); - else - mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); - - memcpy( tmp, prv, 8 ); - memcpy( prv, buf, 8 ); - memcpy( buf, tmp, 8 ); - } - - memcpy( buf, prv, 8 ); - } - - if( ( v == MBEDTLS_DES_DECRYPT && - memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || - ( v != MBEDTLS_DES_DECRYPT && - memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_des_free( &ctx ); - mbedtls_des3_free( &ctx3 ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_DES_C */ diff --git a/components/security/mbedtls/src/dhm.c b/components/security/mbedtls/src/dhm.c deleted file mode 100644 index a4715d17..00000000 --- a/components/security/mbedtls/src/dhm.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Diffie-Hellman-Merkle key exchange - * - * 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) - */ -/* - * The following sources were referenced in the design of this implementation - * of the Diffie-Hellman-Merkle algorithm: - * - * [1] Handbook of Applied Cryptography - 1997, Chapter 12 - * Menezes, van Oorschot and Vanstone - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_DHM_C) - -#include "mbedtls/dhm.h" - -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_ASN1_PARSE_C) -#include "mbedtls/asn1.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* 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; -} - -/* - * helper to validate the mbedtls_mpi size and import it - */ -static int dhm_read_bignum( mbedtls_mpi *X, - unsigned char **p, - const unsigned char *end ) -{ - int ret, n; - - if( end - *p < 2 ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - n = ( (*p)[0] << 8 ) | (*p)[1]; - (*p) += 2; - - if( (int)( end - *p ) < n ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) - return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); - - (*p) += n; - - return( 0 ); -} - -/* - * Verify sanity of parameter with regards to P - * - * Parameter should be: 2 <= public_param <= P - 2 - * - * For more information on the attack, see: - * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf - * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 - */ -static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) -{ - mbedtls_mpi L, U; - int ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; - - mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); - - if( mbedtls_mpi_cmp_mpi( param, &L ) >= 0 && - mbedtls_mpi_cmp_mpi( param, &U ) <= 0 ) - { - ret = 0; - } - -cleanup: - mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); - return( ret ); -} - -void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); -} - -/* - * Parse the ServerKeyExchange parameters - */ -int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, - unsigned char **p, - const unsigned char *end ) -{ - int ret; - - if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || - ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || - ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) - return( ret ); - - if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) - return( ret ); - - ctx->len = mbedtls_mpi_size( &ctx->P ); - - return( 0 ); -} - -/* - * Setup and write the ServerKeyExchange parameters - */ -int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, - unsigned char *output, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count = 0; - size_t n1, n2, n3; - unsigned char *p; - - if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - /* - * Generate X as large as possible ( < P ) - */ - do - { - mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); - - while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); - } - while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); - - /* - * Calculate GX = G^X mod P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, - &ctx->P , &ctx->RP ) ); - - if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) - return( ret ); - - /* - * export P, G, GX - */ -#define DHM_MPI_EXPORT(X,n) \ - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, p + 2, n ) ); \ - *p++ = (unsigned char)( n >> 8 ); \ - *p++ = (unsigned char)( n ); p += n; - - n1 = mbedtls_mpi_size( &ctx->P ); - n2 = mbedtls_mpi_size( &ctx->G ); - n3 = mbedtls_mpi_size( &ctx->GX ); - - p = output; - DHM_MPI_EXPORT( &ctx->P , n1 ); - DHM_MPI_EXPORT( &ctx->G , n2 ); - DHM_MPI_EXPORT( &ctx->GX, n3 ); - - *olen = p - output; - - ctx->len = n1; - -cleanup: - - if( ret != 0 ) - return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); - - return( 0 ); -} - -/* - * Import the peer's public value G^Y - */ -int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, - const unsigned char *input, size_t ilen ) -{ - int ret; - - if( ctx == NULL || ilen < 1 || ilen > ctx->len ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) - return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Create own private value X and export G^X - */ -int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, - unsigned char *output, size_t olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count = 0; - - if( ctx == NULL || olen < 1 || olen > ctx->len ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - /* - * generate X and calculate GX = G^X mod P - */ - do - { - mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); - - while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); - } - while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, - &ctx->P , &ctx->RP ) ); - - if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) - return( ret ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); - -cleanup: - - if( ret != 0 ) - return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Use the blinding method and optimisation suggested in section 10 of: - * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, - * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer - * Berlin Heidelberg, 1996. p. 104-113. - */ -static int dhm_update_blinding( mbedtls_dhm_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret, count; - - /* - * Don't use any blinding the first time a particular X is used, - * but remember it to use blinding next time. - */ - if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); - - return( 0 ); - } - - /* - * Ok, we need blinding. Can we re-use existing values? - * If yes, just update them by squaring them. - */ - if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); - - return( 0 ); - } - - /* - * We need to generate blinding values from scratch - */ - - /* Vi = random( 2, P-1 ) */ - count = 0; - do - { - mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ); - - while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - } - while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); - - /* Vf = Vi^-X mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); - -cleanup: - return( ret ); -} - -/* - * Derive and export the shared secret (G^Y)^X mod P - */ -int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, - unsigned char *output, size_t output_size, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi GYb; - - if( ctx == NULL || output_size < ctx->len ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) - return( ret ); - - mbedtls_mpi_init( &GYb ); - - /* Blind peer's value */ - if( f_rng != NULL ) - { - MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); - } - else - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); - - /* Do modular exponentiation */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, - &ctx->P, &ctx->RP ) ); - - /* Unblind secret value */ - if( f_rng != NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); - } - - *olen = mbedtls_mpi_size( &ctx->K ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); - -cleanup: - mbedtls_mpi_free( &GYb ); - - if( ret != 0 ) - return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); - - return( 0 ); -} - -/* - * Free the components of a DHM key - */ -void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) -{ - mbedtls_mpi_free( &ctx->pX); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->Vi ); - mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); - mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); mbedtls_mpi_free( &ctx->G ); - mbedtls_mpi_free( &ctx->P ); - - mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); -} - -#if defined(MBEDTLS_ASN1_PARSE_C) -/* - * Parse DHM parameters - */ -int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, - size_t dhminlen ) -{ - int ret; - size_t len; - unsigned char *p, *end; -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_context pem; - - mbedtls_pem_init( &pem ); - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN DH PARAMETERS-----", - "-----END DH PARAMETERS-----", - dhmin, NULL, 0, &dhminlen ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - dhminlen = pem.buflen; - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - goto exit; - - p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; -#else - p = (unsigned char *) dhmin; -#endif /* MBEDTLS_PEM_PARSE_C */ - end = p + dhminlen; - - /* - * DHParams ::= SEQUENCE { - * prime INTEGER, -- P - * generator INTEGER, -- g - * privateValueLength INTEGER OPTIONAL - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; - goto exit; - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) - { - ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; - goto exit; - } - - if( p != end ) - { - /* This might be the optional privateValueLength. - * If so, we can cleanly discard it */ - mbedtls_mpi rec; - mbedtls_mpi_init( &rec ); - ret = mbedtls_asn1_get_mpi( &p, end, &rec ); - mbedtls_mpi_free( &rec ); - if ( ret != 0 ) - { - ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; - goto exit; - } - if ( p != end ) - { - ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - goto exit; - } - } - - ret = 0; - - dhm->len = mbedtls_mpi_size( &dhm->P ); - -exit: -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_free( &pem ); -#endif - if( ret != 0 ) - mbedtls_dhm_free( dhm ); - - return( ret ); -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load all data from a file into a given buffer. - * - * The file is expected to contain either PEM or DER encoded data. - * A terminating null byte is always appended. It is included in the announced - * length only if the data looks like it is PEM encoded. - */ -static int load_file( const char *path, unsigned char **buf, size_t *n ) -{ - FILE *f; - long size; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - if( ( size = ftell( f ) ) == -1 ) - { - fclose( f ); - return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); - } - fseek( f, 0, SEEK_SET ); - - *n = (size_t) size; - - if( *n + 1 == 0 || - ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) - { - fclose( f ); - return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); - } - - if( fread( *buf, 1, *n, f ) != *n ) - { - fclose( f ); - mbedtls_free( *buf ); - return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); - } - - fclose( f ); - - (*buf)[*n] = '\0'; - - if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) - ++*n; - - return( 0 ); -} - -/* - * Load and parse DHM parameters - */ -int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ -#endif /* MBEDTLS_ASN1_PARSE_C */ - -#if defined(MBEDTLS_SELF_TEST) - -static const char mbedtls_test_dhm_params[] = -"-----BEGIN DH PARAMETERS-----\r\n" -"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" -"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" -"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" -"-----END DH PARAMETERS-----\r\n"; - -static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); - -/* - * Checkup routine - */ -int mbedtls_dhm_self_test( int verbose ) -{ - int ret; - mbedtls_dhm_context dhm; - - mbedtls_dhm_init( &dhm ); - - if( verbose != 0 ) - mbedtls_printf( " DHM parameter load: " ); - - if( ( ret = mbedtls_dhm_parse_dhm( &dhm, - (const unsigned char *) mbedtls_test_dhm_params, - mbedtls_test_dhm_params_len ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n\n" ); - -exit: - mbedtls_dhm_free( &dhm ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_DHM_C */ diff --git a/components/security/mbedtls/src/ecdh.c b/components/security/mbedtls/src/ecdh.c deleted file mode 100644 index c0a81473..00000000 --- a/components/security/mbedtls/src/ecdh.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Elliptic curve Diffie-Hellman - * - * 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) - */ - -/* - * References: - * - * SEC1 http://www.secg.org/index.php?action=secg,docs_secg - * RFC 4492 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECDH_C) - -#include "mbedtls/ecdh.h" - -#include - -/* - * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair - */ -int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); -} - -/* - * Compute shared secret (SEC1 3.3.1) - */ -int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, - const mbedtls_ecp_point *Q, const mbedtls_mpi *d, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point P; - - mbedtls_ecp_point_init( &P ); - - /* - * Make sure Q is a valid pubkey before using it - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); - - if( mbedtls_ecp_is_zero( &P ) ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); - -cleanup: - mbedtls_ecp_point_free( &P ); - - return( ret ); -} - -/* - * Initialize context - */ -void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); -} - -/* - * Free context - */ -void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_ecp_group_free( &ctx->grp ); - mbedtls_ecp_point_free( &ctx->Q ); - mbedtls_ecp_point_free( &ctx->Qp ); - mbedtls_ecp_point_free( &ctx->Vi ); - mbedtls_ecp_point_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->d ); - mbedtls_mpi_free( &ctx->z ); - mbedtls_mpi_free( &ctx->_d ); -} - -/* - * Setup and write the ServerKeyExhange parameters (RFC 4492) - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; - */ -int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t grp_len, pt_len; - - if( ctx == NULL || ctx->grp.pbits == 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) - return( ret ); - - if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) - != 0 ) - return( ret ); - - buf += grp_len; - blen -= grp_len; - - if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - &pt_len, buf, blen ) ) != 0 ) - return( ret ); - - *olen = grp_len + pt_len; - return( 0 ); -} - -/* - * Read the ServerKeyExhange parameters (RFC 4492) - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; - */ -int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, - const unsigned char **buf, const unsigned char *end ) -{ - int ret; - - if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) - != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Get parameters from a keypair - */ -int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, - mbedtls_ecdh_side side ) -{ - int ret; - - if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) - return( ret ); - - /* If it's not our key, just import the public part as Qp */ - if( side == MBEDTLS_ECDH_THEIRS ) - return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); - - /* Our key: import public (as Q) and private parts */ - if( side != MBEDTLS_ECDH_OURS ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || - ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Setup and export the client public value - */ -int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - - if( ctx == NULL || ctx->grp.pbits == 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) - return( ret ); - - return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - olen, buf, blen ); -} - -/* - * Parse and import the client's public value - */ -int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, - const unsigned char *buf, size_t blen ) -{ - int ret; - const unsigned char *p = buf; - - if( ctx == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 ) - return( ret ); - - if( (size_t)( p - buf ) != blen ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - return( 0 ); -} - -/* - * Derive and export the shared secret - */ -int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - - if( ctx == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, - f_rng, p_rng ) ) != 0 ) - { - return( ret ); - } - - if( mbedtls_mpi_size( &ctx->z ) > blen ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); - return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); -} - -#endif /* MBEDTLS_ECDH_C */ diff --git a/components/security/mbedtls/src/ecdsa.c b/components/security/mbedtls/src/ecdsa.c deleted file mode 100644 index 4156f3c3..00000000 --- a/components/security/mbedtls/src/ecdsa.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Elliptic curve DSA - * - * 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) - */ - -/* - * References: - * - * SEC1 http://www.secg.org/index.php?action=secg,docs_secg - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECDSA_C) - -#include "mbedtls/ecdsa.h" -#include "mbedtls/asn1write.h" - -#include - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -#include "mbedtls/hmac_drbg.h" -#endif - -/* - * Derive a suitable integer for group grp from a buffer of length len - * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 - */ -static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, - const unsigned char *buf, size_t blen ) -{ - int ret; - size_t n_size = ( grp->nbits + 7 ) / 8; - size_t use_size = blen > n_size ? n_size : blen; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); - if( use_size * 8 > grp->nbits ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); - - /* While at it, reduce modulo N */ - if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); - -cleanup: - return( ret ); -} - -/* - * Compute ECDSA signature of a hashed message (SEC1 4.1.3) - * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) - */ -int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret, key_tries, sign_tries, blind_tries; - mbedtls_ecp_point R; - mbedtls_mpi k, e, t; - - /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ - if( grp->N.p == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - mbedtls_ecp_point_init( &R ); - mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); - - sign_tries = 0; - do - { - /* - * Steps 1-3: generate a suitable ephemeral keypair - * and set r = xR mod n - */ - key_tries = 0; - do - { - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); - - if( key_tries++ > 10 ) - { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } - } - while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); - - /* - * Step 5: derive MPI from hashed message - */ - MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); - - /* - * Generate a random value to blind inv_mod in next step, - * avoiding a potential timing leak. - */ - blind_tries = 0; - do - { - size_t n_size = ( grp->nbits + 7 ) / 8; - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); - - /* See mbedtls_ecp_gen_keypair() */ - if( ++blind_tries > 30 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); - - /* - * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); - - if( sign_tries++ > 10 ) - { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } - } - while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); - -cleanup: - mbedtls_ecp_point_free( &R ); - mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); - - return( ret ); -} - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -/* - * Deterministic signature wrapper - */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ) -{ - int ret; - mbedtls_hmac_drbg_context rng_ctx; - unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; - size_t grp_len = ( grp->nbits + 7 ) / 8; - const mbedtls_md_info_t *md_info; - mbedtls_mpi h; - - if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &h ); - mbedtls_hmac_drbg_init( &rng_ctx ); - - /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); - MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); - mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); - - ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, - mbedtls_hmac_drbg_random, &rng_ctx ); - -cleanup: - mbedtls_hmac_drbg_free( &rng_ctx ); - mbedtls_mpi_free( &h ); - - return( ret ); -} -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - -/* - * Verify ECDSA signature of hashed message (SEC1 4.1.4) - * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) - */ -int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) -{ - int ret; - mbedtls_mpi e, s_inv, u1, u2; - mbedtls_ecp_point R; - - mbedtls_ecp_point_init( &R ); - mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); - - /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ - if( grp->N.p == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Step 1: make sure r and s are in range 1..n-1 - */ - if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || - mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) - { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - - /* - * Additional precaution: make sure Q is valid - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - - /* - * Step 3: derive MPI from hashed message - */ - MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); - - /* - * Step 4: u1 = e / s mod n, u2 = r / s mod n - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); - - /* - * Step 5: R = u1 G + u2 Q - * - * Since we're not using any secret data, no need to pass a RNG to - * mbedtls_ecp_mul() for countermesures. - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); - - if( mbedtls_ecp_is_zero( &R ) ) - { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - - /* - * Step 6: convert xR to an integer (no-op) - * Step 7: reduce xR mod n (gives v) - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); - - /* - * Step 8: check if v (that is, R.X) is equal to r - */ - if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) - { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - -cleanup: - mbedtls_ecp_point_free( &R ); - mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); - - return( ret ); -} - -/* - * Convert a signature (given by context) to ASN.1 - */ -static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, - unsigned char *sig, size_t *slen ) -{ - int ret; - unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; - unsigned char *p = buf + sizeof( buf ); - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); - - memcpy( sig, p, len ); - *slen = len; - - return( 0 ); -} - -/* - * Compute and write signature - */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi r, s; - - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &s ); - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) - (void) f_rng; - (void) p_rng; - - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, - hash, hlen, md_alg ) ); -#else - (void) md_alg; - - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, - hash, hlen, f_rng, p_rng ) ); -#endif - - MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); - -cleanup: - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &s ); - - return( ret ); -} - -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ - defined(MBEDTLS_ECDSA_DETERMINISTIC) -int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - mbedtls_md_type_t md_alg ) -{ - return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, - NULL, NULL ) ); -} -#endif - -/* - * Read and check signature - */ -int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen ) -{ - int ret; - unsigned char *p = (unsigned char *) sig; - const unsigned char *end = sig + slen; - size_t len; - mbedtls_mpi r, s; - - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &s ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - if( p + len != end ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - goto cleanup; - } - - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) - { - ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, - &ctx->Q, &r, &s ) ) != 0 ) - goto cleanup; - - if( p != end ) - ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; - -cleanup: - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &s ); - - return( ret ); -} - -/* - * Generate key pair - */ -int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - return( mbedtls_ecp_group_load( &ctx->grp, gid ) || - mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); -} - -/* - * Set context from an mbedtls_ecp_keypair - */ -int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) -{ - int ret; - - if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || - ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || - ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) - { - mbedtls_ecdsa_free( ctx ); - } - - return( ret ); -} - -/* - * Initialize context - */ -void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) -{ - mbedtls_ecp_keypair_init( ctx ); -} - -/* - * Free context - */ -void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) -{ - mbedtls_ecp_keypair_free( ctx ); -} - -#endif /* MBEDTLS_ECDSA_C */ diff --git a/components/security/mbedtls/src/ecjpake.c b/components/security/mbedtls/src/ecjpake.c deleted file mode 100644 index 1fa1c2d8..00000000 --- a/components/security/mbedtls/src/ecjpake.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * Elliptic curve J-PAKE - * - * 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) - */ - -/* - * References in the code are to the Thread v1.0 Specification, - * available to members of the Thread Group http://threadgroup.org/ - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECJPAKE_C) - -#include "mbedtls/ecjpake.h" - -#include - -/* - * Convert a mbedtls_ecjpake_role to identifier string - */ -static const char * const ecjpake_id[] = { - "client", - "server" -}; - -#define ID_MINE ( ecjpake_id[ ctx->role ] ) -#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) - -/* - * Initialize context - */ -void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) -{ - if( ctx == NULL ) - return; - - ctx->md_info = NULL; - mbedtls_ecp_group_init( &ctx->grp ); - ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; - - mbedtls_ecp_point_init( &ctx->Xm1 ); - mbedtls_ecp_point_init( &ctx->Xm2 ); - mbedtls_ecp_point_init( &ctx->Xp1 ); - mbedtls_ecp_point_init( &ctx->Xp2 ); - mbedtls_ecp_point_init( &ctx->Xp ); - - mbedtls_mpi_init( &ctx->xm1 ); - mbedtls_mpi_init( &ctx->xm2 ); - mbedtls_mpi_init( &ctx->s ); -} - -/* - * Free context - */ -void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) -{ - if( ctx == NULL ) - return; - - ctx->md_info = NULL; - mbedtls_ecp_group_free( &ctx->grp ); - - mbedtls_ecp_point_free( &ctx->Xm1 ); - mbedtls_ecp_point_free( &ctx->Xm2 ); - mbedtls_ecp_point_free( &ctx->Xp1 ); - mbedtls_ecp_point_free( &ctx->Xp2 ); - mbedtls_ecp_point_free( &ctx->Xp ); - - mbedtls_mpi_free( &ctx->xm1 ); - mbedtls_mpi_free( &ctx->xm2 ); - mbedtls_mpi_free( &ctx->s ); -} - -/* - * Setup context - */ -int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, - mbedtls_ecjpake_role role, - mbedtls_md_type_t hash, - mbedtls_ecp_group_id curve, - const unsigned char *secret, - size_t len ) -{ - int ret; - - ctx->role = role; - - if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) - return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); - -cleanup: - if( ret != 0 ) - mbedtls_ecjpake_free( ctx ); - - return( ret ); -} - -/* - * Check if context is ready for use - */ -int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) -{ - if( ctx->md_info == NULL || - ctx->grp.id == MBEDTLS_ECP_DP_NONE || - ctx->s.p == NULL ) - { - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - } - - return( 0 ); -} - -/* - * Write a point plus its length to a buffer - */ -static int ecjpake_write_len_point( unsigned char **p, - const unsigned char *end, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *P ) -{ - int ret; - size_t len; - - /* Need at least 4 for length plus 1 for point */ - if( end < *p || end - *p < 5 ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - ret = mbedtls_ecp_point_write_binary( grp, P, pf, - &len, *p + 4, end - ( *p + 4 ) ); - if( ret != 0 ) - return( ret ); - - (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF ); - (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF ); - (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF ); - (*p)[3] = (unsigned char)( ( len ) & 0xFF ); - - *p += 4 + len; - - return( 0 ); -} - -/* - * Size of the temporary buffer for ecjpake_hash: - * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) - */ -#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) - -/* - * Compute hash for ZKP (7.4.2.2.2.1) - */ -static int ecjpake_hash( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - const mbedtls_ecp_point *V, - const mbedtls_ecp_point *X, - const char *id, - mbedtls_mpi *h ) -{ - int ret; - unsigned char buf[ECJPAKE_HASH_BUF_LEN]; - unsigned char *p = buf; - const unsigned char *end = buf + sizeof( buf ); - const size_t id_len = strlen( id ); - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - - /* Write things to temporary buffer */ - MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); - MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); - MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); - - if( end - p < 4 ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF ); - *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF ); - *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( id_len ) & 0xFF ); - - if( end < p || (size_t)( end - p ) < id_len ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - memcpy( p, id, id_len ); - p += id_len; - - /* Compute hash */ - mbedtls_md( md_info, buf, p - buf, hash ); - - /* Turn it into an integer mod n */ - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, - mbedtls_md_get_size( md_info ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); - -cleanup: - return( ret ); -} - -/* - * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) - */ -static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - const mbedtls_ecp_point *X, - const char *id, - const unsigned char **p, - const unsigned char *end ) -{ - int ret; - mbedtls_ecp_point V, VV; - mbedtls_mpi r, h; - size_t r_len; - - mbedtls_ecp_point_init( &V ); - mbedtls_ecp_point_init( &VV ); - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &h ); - - /* - * struct { - * ECPoint V; - * opaque r<1..2^8-1>; - * } ECSchnorrZKP; - */ - if( end < *p ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); - - if( end < *p || (size_t)( end - *p ) < 1 ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - r_len = *(*p)++; - - if( end < *p || (size_t)( end - *p ) < r_len ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); - *p += r_len; - - /* - * Verification - */ - MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, - &VV, &h, X, &r, G ) ); - - if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) - { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - -cleanup: - mbedtls_ecp_point_free( &V ); - mbedtls_ecp_point_free( &VV ); - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &h ); - - return( ret ); -} - -/* - * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) - */ -static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - const mbedtls_mpi *x, - const mbedtls_ecp_point *X, - const char *id, - unsigned char **p, - const unsigned char *end, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point V; - mbedtls_mpi v; - mbedtls_mpi h; /* later recycled to hold r */ - size_t len; - - if( end < *p ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - mbedtls_ecp_point_init( &V ); - mbedtls_mpi_init( &v ); - mbedtls_mpi_init( &h ); - - /* Compute signature */ - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, - G, &v, &V, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ - - /* Write it out */ - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, - pf, &len, *p, end - *p ) ); - *p += len; - - len = mbedtls_mpi_size( &h ); /* actually r */ - if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) - { - ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - goto cleanup; - } - - *(*p)++ = (unsigned char)( len & 0xFF ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ - *p += len; - -cleanup: - mbedtls_ecp_point_free( &V ); - mbedtls_mpi_free( &v ); - mbedtls_mpi_free( &h ); - - return( ret ); -} - -/* - * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof - * Output: verified public key X - */ -static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - mbedtls_ecp_point *X, - const char *id, - const unsigned char **p, - const unsigned char *end ) -{ - int ret; - - if( end < *p ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * struct { - * ECPoint X; - * ECSchnorrZKP zkp; - * } ECJPAKEKeyKP; - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); - if( mbedtls_ecp_is_zero( X ) ) - { - ret = MBEDTLS_ERR_ECP_INVALID_KEY; - goto cleanup; - } - - MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); - -cleanup: - return( ret ); -} - -/* - * Generate an ECJPAKEKeyKP - * Output: the serialized structure, plus private/public key pair - */ -static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - mbedtls_mpi *x, - mbedtls_ecp_point *X, - const char *id, - unsigned char **p, - const unsigned char *end, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t len; - - if( end < *p ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - /* Generate key (7.4.2.3.1) and write it out */ - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, - f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, - pf, &len, *p, end - *p ) ); - *p += len; - - /* Generate and write proof */ - MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, - p, end, f_rng, p_rng ) ); - -cleanup: - return( ret ); -} - -/* - * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs - * Ouputs: verified peer public keys Xa, Xb - */ -static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - mbedtls_ecp_point *Xa, - mbedtls_ecp_point *Xb, - const char *id, - const unsigned char *buf, - size_t len ) -{ - int ret; - const unsigned char *p = buf; - const unsigned char *end = buf + len; - - /* - * struct { - * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; - * } ECJPAKEKeyKPPairList; - */ - MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); - MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); - - if( p != end ) - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - -cleanup: - return( ret ); -} - -/* - * Generate a ECJPAKEKeyKPPairList - * Outputs: the serialized structure, plus two private/public key pairs - */ -static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - mbedtls_mpi *xm1, - mbedtls_ecp_point *Xa, - mbedtls_mpi *xm2, - mbedtls_ecp_point *Xb, - const char *id, - unsigned char *buf, - size_t len, - size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char *p = buf; - const unsigned char *end = buf + len; - - MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, - &p, end, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, - &p, end, f_rng, p_rng ) ); - - *olen = p - buf; - -cleanup: - return( ret ); -} - -/* - * Read and process the first round message - */ -int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, - const unsigned char *buf, - size_t len ) -{ - return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, - &ctx->grp.G, - &ctx->Xp1, &ctx->Xp2, ID_PEER, - buf, len ) ); -} - -/* - * Generate and write the first round message - */ -int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, - &ctx->grp.G, - &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, - ID_MINE, buf, len, olen, f_rng, p_rng ) ); -} - -/* - * Compute the sum of three points R = A + B + C - */ -static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point *A, - const mbedtls_ecp_point *B, - const mbedtls_ecp_point *C ) -{ - int ret; - mbedtls_mpi one; - - mbedtls_mpi_init( &one ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); - -cleanup: - mbedtls_mpi_free( &one ); - - return( ret ); -} - -/* - * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) - */ -int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, - const unsigned char *buf, - size_t len ) -{ - int ret; - const unsigned char *p = buf; - const unsigned char *end = buf + len; - mbedtls_ecp_group grp; - mbedtls_ecp_point G; /* C: GB, S: GA */ - - mbedtls_ecp_group_init( &grp ); - mbedtls_ecp_point_init( &G ); - - /* - * Server: GA = X3 + X4 + X1 (7.4.2.6.1) - * Client: GB = X1 + X2 + X3 (7.4.2.5.1) - * Unified: G = Xm1 + Xm2 + Xp1 - * We need that before parsing in order to check Xp as we read it - */ - MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, - &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); - - /* - * struct { - * ECParameters curve_params; // only client reading server msg - * ECJPAKEKeyKP ecjpake_key_kp; - * } Client/ServerECJPAKEParams; - */ - if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) - { - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); - if( grp.id != ctx->grp.id ) - { - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - goto cleanup; - } - } - - MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, - ctx->point_format, - &G, &ctx->Xp, ID_PEER, &p, end ) ); - - if( p != end ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - -cleanup: - mbedtls_ecp_group_free( &grp ); - mbedtls_ecp_point_free( &G ); - - return( ret ); -} - -/* - * Compute R = +/- X * S mod N, taking care not to leak S - */ -static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, - const mbedtls_mpi *X, - const mbedtls_mpi *S, - const mbedtls_mpi *N, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi b; /* Blinding value, then s + N * blinding */ - - mbedtls_mpi_init( &b ); - - /* b = s + rnd-128-bit * N */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); - - /* R = sign * X * b mod N */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); - R->s *= sign; - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); - -cleanup: - mbedtls_mpi_free( &b ); - - return( ret ); -} - -/* - * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) - */ -int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point G; /* C: GA, S: GB */ - mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ - mbedtls_mpi xm; /* C: xc, S: xs */ - unsigned char *p = buf; - const unsigned char *end = buf + len; - size_t ec_len; - - mbedtls_ecp_point_init( &G ); - mbedtls_ecp_point_init( &Xm ); - mbedtls_mpi_init( &xm ); - - /* - * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) - * - * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA - * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB - * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G - */ - MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, - &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); - MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, - &ctx->grp.N, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); - - /* - * Now write things out - * - * struct { - * ECParameters curve_params; // only server writing its message - * ECJPAKEKeyKP ecjpake_key_kp; - * } Client/ServerECJPAKEParams; - */ - if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) - { - if( end < p ) - { - ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - goto cleanup; - } - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, - p, end - p ) ); - p += ec_len; - } - - if( end < p ) - { - ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - goto cleanup; - } - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, - ctx->point_format, &ec_len, p, end - p ) ); - p += ec_len; - - MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, - ctx->point_format, - &G, &xm, &Xm, ID_MINE, - &p, end, f_rng, p_rng ) ); - - *olen = p - buf; - -cleanup: - mbedtls_ecp_point_free( &G ); - mbedtls_ecp_point_free( &Xm ); - mbedtls_mpi_free( &xm ); - - return( ret ); -} - -/* - * Derive PMS (7.4.2.7 / 7.4.2.8) - */ -int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point K; - mbedtls_mpi m_xm2_s, one; - unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; - size_t x_bytes; - - *olen = mbedtls_md_get_size( ctx->md_info ); - if( len < *olen ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - mbedtls_ecp_point_init( &K ); - mbedtls_mpi_init( &m_xm2_s ); - mbedtls_mpi_init( &one ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); - - /* - * Client: K = ( Xs - X4 * x2 * s ) * x2 - * Server: K = ( Xc - X2 * x4 * s ) * x4 - * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 - */ - MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, - &ctx->grp.N, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, - &one, &ctx->Xp, - &m_xm2_s, &ctx->Xp2 ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, - f_rng, p_rng ) ); - - /* PMS = SHA-256( K.X ) */ - x_bytes = ( ctx->grp.pbits + 7 ) / 8; - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); - MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); - -cleanup: - mbedtls_ecp_point_free( &K ); - mbedtls_mpi_free( &m_xm2_s ); - mbedtls_mpi_free( &one ); - - return( ret ); -} - -#undef ID_MINE -#undef ID_PEER - - -#if defined(MBEDTLS_SELF_TEST) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif - -#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - !defined(MBEDTLS_SHA256_C) -int mbedtls_ecjpake_self_test( int verbose ) -{ - (void) verbose; - return( 0 ); -} -#else - -static const unsigned char ecjpake_test_password[] = { - 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, - 0x65, 0x73, 0x74 -}; - -static const unsigned char ecjpake_test_x1[] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, - 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 -}; - -static const unsigned char ecjpake_test_x2[] = { - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, - 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 -}; - -static const unsigned char ecjpake_test_x3[] = { - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, - 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 -}; - -static const unsigned char ecjpake_test_x4[] = { - 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, - 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 -}; - -static const unsigned char ecjpake_test_cli_one[] = { - 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, - 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, - 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, - 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, - 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, - 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, - 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, - 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, - 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, - 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, - 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, - 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, - 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, - 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, - 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, - 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, - 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, - 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, - 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, - 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, - 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, - 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, - 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, - 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, - 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, - 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, - 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, - 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 -}; - -static const unsigned char ecjpake_test_srv_one[] = { - 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, - 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, - 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, - 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, - 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, - 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, - 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, - 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, - 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, - 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, - 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, - 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, - 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, - 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, - 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, - 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, - 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, - 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, - 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, - 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, - 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, - 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, - 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, - 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, - 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, - 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, - 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, - 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 -}; - -static const unsigned char ecjpake_test_srv_two[] = { - 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, - 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, - 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, - 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, - 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, - 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, - 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, - 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, - 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, - 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, - 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, - 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, - 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, - 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c -}; - -static const unsigned char ecjpake_test_cli_two[] = { - 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, - 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, - 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, - 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, - 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, - 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, - 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, - 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, - 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, - 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, - 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, - 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, - 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, - 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c -}; - -static const unsigned char ecjpake_test_pms[] = { - 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, - 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, - 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 -}; - -/* Load my private keys and generate the correponding public keys */ -static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, - const unsigned char *xm1, size_t len1, - const unsigned char *xm2, size_t len2 ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, - &ctx->grp.G, NULL, NULL ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, - &ctx->grp.G, NULL, NULL ) ); - -cleanup: - return( ret ); -} - -/* For tests we don't need a secure RNG; - * use the LGC from Numerical Recipes for simplicity */ -static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) -{ - static uint32_t x = 42; - (void) p; - - while( len > 0 ) - { - size_t use_len = len > 4 ? 4 : len; - x = 1664525 * x + 1013904223; - memcpy( out, &x, use_len ); - out += use_len; - len -= use_len; - } - - return( 0 ); -} - -#define TEST_ASSERT( x ) \ - do { \ - if( x ) \ - ret = 0; \ - else \ - { \ - ret = 1; \ - goto cleanup; \ - } \ - } while( 0 ) - -/* - * Checkup routine - */ -int mbedtls_ecjpake_self_test( int verbose ) -{ - int ret; - mbedtls_ecjpake_context cli; - mbedtls_ecjpake_context srv; - unsigned char buf[512], pms[32]; - size_t len, pmslen; - - mbedtls_ecjpake_init( &cli ); - mbedtls_ecjpake_init( &srv ); - - if( verbose != 0 ) - mbedtls_printf( " ECJPAKE test #0 (setup): " ); - - TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, - MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, - ecjpake_test_password, - sizeof( ecjpake_test_password ) ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, - MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, - ecjpake_test_password, - sizeof( ecjpake_test_password ) ) == 0 ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); - - TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, - pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( len == pmslen ); - TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); - - /* Simulate generation of round one */ - MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, - ecjpake_test_x1, sizeof( ecjpake_test_x1 ), - ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); - - MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, - ecjpake_test_x3, sizeof( ecjpake_test_x3 ), - ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); - - /* Read round one */ - TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, - ecjpake_test_cli_one, - sizeof( ecjpake_test_cli_one ) ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, - ecjpake_test_srv_one, - sizeof( ecjpake_test_srv_one ) ) == 0 ); - - /* Skip generation of round two, read round two */ - TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, - ecjpake_test_srv_two, - sizeof( ecjpake_test_srv_two ) ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, - ecjpake_test_cli_two, - sizeof( ecjpake_test_cli_two ) ) == 0 ); - - /* Server derives PMS */ - TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); - TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); - - memset( buf, 0, len ); /* Avoid interferences with next step */ - - /* Client derives PMS */ - TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); - TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - mbedtls_ecjpake_free( &cli ); - mbedtls_ecjpake_free( &srv ); - - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( ret ); -} - -#undef TEST_ASSERT - -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_ECJPAKE_C */ diff --git a/components/security/mbedtls/src/ecp.c b/components/security/mbedtls/src/ecp.c deleted file mode 100644 index 56f22c27..00000000 --- a/components/security/mbedtls/src/ecp.c +++ /dev/null @@ -1,2217 +0,0 @@ -/* - * Elliptic curves over GF(p): generic 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) - */ - -/* - * References: - * - * SEC1 http://www.secg.org/index.php?action=secg,docs_secg - * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone - * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf - * RFC 4492 for the related TLS structures and constants - * - * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf - * - * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis - * for elliptic curve cryptosystems. In : Cryptographic Hardware and - * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. - * - * - * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to - * render ECC resistant against Side Channel Attacks. IACR Cryptology - * ePrint Archive, 2004, vol. 2004, p. 342. - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECP_C) - -#include "mbedtls/ecp.h" -#include "mbedtls/threading.h" - -#include - -#if !defined(MBEDTLS_ECP_ALT) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/ecp_internal.h" - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -/* 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; -} - -#if defined(MBEDTLS_SELF_TEST) -/* - * Counts of point addition and doubling, and field multiplications. - * Used to test resistance of point multiplication to simple timing attacks. - */ -static unsigned long add_count, dbl_count, mul_count; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -#define ECP_SHORTWEIERSTRASS -#endif - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -#define ECP_MONTGOMERY -#endif - -/* - * Curve types: internal for now, might be exposed later - */ -typedef enum -{ - ECP_TYPE_NONE = 0, - ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ - ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ -} ecp_curve_type; - -/* - * List of supported curves: - * - internal ID - * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) - * - size in bits - * - readable name - * - * Curves are listed in order: largest curves first, and for a given size, - * fastest curves first. This provides the default order for the SSL module. - * - * Reminder: update profiles in x509_crt.c when adding a new curves! - */ -static const mbedtls_ecp_curve_info ecp_supported_curves[] = -{ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, -#endif -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, -#endif - { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, -}; - -#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ - sizeof( ecp_supported_curves[0] ) - -static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; - -/* - * List of supported curves and associated info - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) -{ - return( ecp_supported_curves ); -} - -/* - * List of supported curves, group ID only - */ -const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) -{ - static int init_done = 0; - - if( ! init_done ) - { - size_t i = 0; - const mbedtls_ecp_curve_info *curve_info; - - for( curve_info = mbedtls_ecp_curve_list(); - curve_info->grp_id != MBEDTLS_ECP_DP_NONE; - curve_info++ ) - { - ecp_supported_grp_id[i++] = curve_info->grp_id; - } - ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; - - init_done = 1; - } - - return( ecp_supported_grp_id ); -} - -/* - * Get the curve info for the internal identifier - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) -{ - const mbedtls_ecp_curve_info *curve_info; - - for( curve_info = mbedtls_ecp_curve_list(); - curve_info->grp_id != MBEDTLS_ECP_DP_NONE; - curve_info++ ) - { - if( curve_info->grp_id == grp_id ) - return( curve_info ); - } - - return( NULL ); -} - -/* - * Get the curve info from the TLS identifier - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) -{ - const mbedtls_ecp_curve_info *curve_info; - - for( curve_info = mbedtls_ecp_curve_list(); - curve_info->grp_id != MBEDTLS_ECP_DP_NONE; - curve_info++ ) - { - if( curve_info->tls_id == tls_id ) - return( curve_info ); - } - - return( NULL ); -} - -/* - * Get the curve info from the name - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) -{ - const mbedtls_ecp_curve_info *curve_info; - - for( curve_info = mbedtls_ecp_curve_list(); - curve_info->grp_id != MBEDTLS_ECP_DP_NONE; - curve_info++ ) - { - if( strcmp( curve_info->name, name ) == 0 ) - return( curve_info ); - } - - return( NULL ); -} - -/* - * Get the type of a curve - */ -static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) -{ - if( grp->G.X.p == NULL ) - return( ECP_TYPE_NONE ); - - if( grp->G.Y.p == NULL ) - return( ECP_TYPE_MONTGOMERY ); - else - return( ECP_TYPE_SHORT_WEIERSTRASS ); -} - -/* - * Initialize (the components of) a point - */ -void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) -{ - if( pt == NULL ) - return; - - mbedtls_mpi_init( &pt->X ); - mbedtls_mpi_init( &pt->Y ); - mbedtls_mpi_init( &pt->Z ); -} - -/* - * Initialize (the components of) a group - */ -void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) -{ - if( grp == NULL ) - return; - - memset( grp, 0, sizeof( mbedtls_ecp_group ) ); -} - -/* - * Initialize (the components of) a key pair - */ -void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) -{ - if( key == NULL ) - return; - - mbedtls_ecp_group_init( &key->grp ); - mbedtls_mpi_init( &key->d ); - mbedtls_ecp_point_init( &key->Q ); -} - -/* - * Unallocate (the components of) a point - */ -void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) -{ - if( pt == NULL ) - return; - - mbedtls_mpi_free( &( pt->X ) ); - mbedtls_mpi_free( &( pt->Y ) ); - mbedtls_mpi_free( &( pt->Z ) ); -} - -/* - * Unallocate (the components of) a group - */ -void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) -{ - size_t i; - - if( grp == NULL ) - return; - - if( grp->h != 1 ) - { - mbedtls_mpi_free( &grp->P ); - mbedtls_mpi_free( &grp->A ); - mbedtls_mpi_free( &grp->B ); - mbedtls_ecp_point_free( &grp->G ); - mbedtls_mpi_free( &grp->N ); - } - - if( grp->T != NULL ) - { - for( i = 0; i < grp->T_size; i++ ) - mbedtls_ecp_point_free( &grp->T[i] ); - mbedtls_free( grp->T ); - } - - mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); -} - -/* - * Unallocate (the components of) a key pair - */ -void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) -{ - if( key == NULL ) - return; - - mbedtls_ecp_group_free( &key->grp ); - mbedtls_mpi_free( &key->d ); - mbedtls_ecp_point_free( &key->Q ); -} - -/* - * Copy the contents of a point - */ -int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); - -cleanup: - return( ret ); -} - -/* - * Copy the contents of a group object - */ -int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) -{ - return mbedtls_ecp_group_load( dst, src->id ); -} - -/* - * Set point to zero - */ -int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); - -cleanup: - return( ret ); -} - -/* - * Tell if a point is zero - */ -int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) -{ - return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); -} - -/* - * Compare two points lazyly - */ -int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q ) -{ - if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && - mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && - mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) - { - return( 0 ); - } - - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); -} - -/* - * Import a non-zero point from ASCII strings - */ -int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, - const char *x, const char *y ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); - -cleanup: - return( ret ); -} - -/* - * Export a point into unsigned binary data (SEC1 2.3.3) - */ -int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, - int format, size_t *olen, - unsigned char *buf, size_t buflen ) -{ - int ret = 0; - size_t plen; - - if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && - format != MBEDTLS_ECP_PF_COMPRESSED ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Common case: P == 0 - */ - if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) - { - if( buflen < 1 ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - buf[0] = 0x00; - *olen = 1; - - return( 0 ); - } - - plen = mbedtls_mpi_size( &grp->P ); - - if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) - { - *olen = 2 * plen + 1; - - if( buflen < *olen ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - buf[0] = 0x04; - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); - } - else if( format == MBEDTLS_ECP_PF_COMPRESSED ) - { - *olen = plen + 1; - - if( buflen < *olen ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); - } - -cleanup: - return( ret ); -} - -/* - * Import a point from unsigned binary data (SEC1 2.3.4) - */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char *buf, size_t ilen ) -{ - int ret; - size_t plen; - - if( ilen < 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( buf[0] == 0x00 ) - { - if( ilen == 1 ) - return( mbedtls_ecp_set_zero( pt ) ); - else - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - } - - plen = mbedtls_mpi_size( &grp->P ); - - if( buf[0] != 0x04 ) - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - - if( ilen != 2 * plen + 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); - -cleanup: - return( ret ); -} - -/* - * Import a point from a TLS ECPoint record (RFC 4492) - * struct { - * opaque point <1..2^8-1>; - * } ECPoint; - */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t buf_len ) -{ - unsigned char data_len; - const unsigned char *buf_start; - - /* - * We must have at least two bytes (1 for length, at least one for data) - */ - if( buf_len < 2 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - data_len = *(*buf)++; - if( data_len < 1 || data_len > buf_len - 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Save buffer start for read_binary and update buf - */ - buf_start = *buf; - *buf += data_len; - - return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); -} - -/* - * Export a point as a TLS ECPoint record (RFC 4492) - * struct { - * opaque point <1..2^8-1>; - * } ECPoint; - */ -int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, - int format, size_t *olen, - unsigned char *buf, size_t blen ) -{ - int ret; - - /* - * buffer length must be at least one, for our length byte - */ - if( blen < 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, - olen, buf + 1, blen - 1) ) != 0 ) - return( ret ); - - /* - * write length to the first byte and update total length - */ - buf[0] = (unsigned char) *olen; - ++*olen; - - return( 0 ); -} - -/* - * Set a group from an ECParameters record (RFC 4492) - */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) -{ - uint16_t tls_id; - const mbedtls_ecp_curve_info *curve_info; - - /* - * We expect at least three bytes (see below) - */ - if( len < 3 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * First byte is curve_type; only named_curve is handled - */ - if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Next two bytes are the namedcurve value - */ - tls_id = *(*buf)++; - tls_id <<= 8; - tls_id |= *(*buf)++; - - if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - - return mbedtls_ecp_group_load( grp, curve_info->grp_id ); -} - -/* - * Write the ECParameters record corresponding to a group (RFC 4492) - */ -int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, - unsigned char *buf, size_t blen ) -{ - const mbedtls_ecp_curve_info *curve_info; - - if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * We are going to write 3 bytes (see below) - */ - *olen = 3; - if( blen < *olen ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - /* - * First byte is curve_type, always named_curve - */ - *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; - - /* - * Next two bytes are the namedcurve value - */ - buf[0] = curve_info->tls_id >> 8; - buf[1] = curve_info->tls_id & 0xFF; - - return( 0 ); -} - -/* - * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. - * See the documentation of struct mbedtls_ecp_group. - * - * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. - */ -static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) -{ - int ret; - - if( grp->modp == NULL ) - return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); - - /* N->s < 0 is a much faster test, which fails only if N is 0 */ - if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || - mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) - { - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - } - - MBEDTLS_MPI_CHK( grp->modp( N ) ); - - /* N->s < 0 is a much faster test, which fails only if N is 0 */ - while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); - - while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) - /* we known P, N and the result are positive */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); - -cleanup: - return( ret ); -} - -/* - * Fast mod-p functions expect their argument to be in the 0..p^2 range. - * - * In order to guarantee that, we need to ensure that operands of - * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will - * bring the result back to this range. - * - * The following macros are shortcuts for doing that. - */ - -/* - * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi - */ -#if defined(MBEDTLS_SELF_TEST) -#define INC_MUL_COUNT mul_count++; -#else -#define INC_MUL_COUNT -#endif - -#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ - while( 0 ) - -/* - * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi - * N->s < 0 is a very fast test, which fails only if N is 0 - */ -#define MOD_SUB( N ) \ - while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) ) - -/* - * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. - * We known P, N and the result are positive, so sub_abs is correct, and - * a bit faster. - */ -#define MOD_ADD( N ) \ - while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) ) - -#if defined(ECP_SHORTWEIERSTRASS) -/* - * For curves in short Weierstrass form, we do all the internal operations in - * Jacobian coordinates. - * - * For multiplication, we'll use a comb method with coutermeasueres against - * SPA, hence timing attacks. - */ - -/* - * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) - * Cost: 1N := 1I + 3M + 1S - */ -static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) -{ - int ret; - mbedtls_mpi Zi, ZZi; - - if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) - return( 0 ); - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_jac( grp, pt ); - } -#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ - mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); - - /* - * X = X / Z^2 mod p - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); - - /* - * Y = Y / Z^3 mod p - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); - - /* - * Z = 1 - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); - -cleanup: - - mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); - - return( ret ); -} - -/* - * Normalize jacobian coordinates of an array of (pointers to) points, - * using Montgomery's trick to perform only one inversion mod P. - * (See for example Cohen's "A Course in Computational Algebraic Number - * Theory", Algorithm 10.3.4.) - * - * Warning: fails (returning an error) if one of the points is zero! - * This should never happen, see choice of w in ecp_mul_comb(). - * - * Cost: 1N(t) := 1I + (6t - 3)M + 1S - */ -static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *T[], size_t t_len ) -{ - int ret; - size_t i; - mbedtls_mpi *c, u, Zi, ZZi; - - if( t_len < 2 ) - return( ecp_normalize_jac( grp, *T ) ); - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len); - } -#endif - - if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) - return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); - - mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); - - /* - * c[i] = Z_0 * ... * Z_i - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); - for( i = 1; i < t_len; i++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); - MOD_MUL( c[i] ); - } - - /* - * u = 1 / (Z_0 * ... * Z_n) mod P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); - - for( i = t_len - 1; ; i-- ) - { - /* - * Zi = 1 / Z_i mod p - * u = 1 / (Z_0 * ... * Z_i) mod P - */ - if( i == 0 ) { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); - } - - /* - * proceed as in normalize() - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); - - /* - * Post-precessing: reclaim some memory by shrinking coordinates - * - not storing Z (always 1) - * - shrinking other coordinates, but still keeping the same number of - * limbs as P, as otherwise it will too likely be regrown too fast. - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); - mbedtls_mpi_free( &T[i]->Z ); - - if( i == 0 ) - break; - } - -cleanup: - - mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); - for( i = 0; i < t_len; i++ ) - mbedtls_mpi_free( &c[i] ); - mbedtls_free( c ); - - return( ret ); -} - -/* - * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. - * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid - */ -static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *Q, - unsigned char inv ) -{ - int ret; - unsigned char nonzero; - mbedtls_mpi mQY; - - mbedtls_mpi_init( &mQY ); - - /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); - nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); - -cleanup: - mbedtls_mpi_free( &mQY ); - - return( ret ); -} - -/* - * Point doubling R = 2 P, Jacobian coordinates - * - * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . - * - * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR - * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. - * - * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. - * - * Cost: 1D := 3M + 4S (A == 0) - * 4M + 4S (A == -3) - * 3M + 6S + 1a otherwise - */ -static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point *P ) -{ - int ret; - mbedtls_mpi M, S, T, U; - -#if defined(MBEDTLS_SELF_TEST) - dbl_count++; -#endif - -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_double_jac( grp, R, P ); - } -#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ - - mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); - - /* Special case for A = -3 */ - if( grp->A.p == NULL ) - { - /* M = 3(X + Z^2)(X - Z^2) */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); - } - else - { - /* M = 3.X^2 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); - - /* Optimize away for "koblitz" curves with A = 0 */ - if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) - { - /* M += A.Z^4 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); - } - } - - /* S = 4.X.Y^2 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); - - /* U = 8.Y^4 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); - - /* T = M^2 - 2.S */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); - - /* S = M(S - T) - U */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); - - /* U = 2.Y.Z */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); - -cleanup: - mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); - - return( ret ); -} - -/* - * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) - * - * The coordinates of Q must be normalized (= affine), - * but those of P don't need to. R is not normalized. - * - * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. - * None of these cases can happen as intermediate step in ecp_mul_comb(): - * - at each step, P, Q and R are multiples of the base point, the factor - * being less than its order, so none of them is zero; - * - Q is an odd multiple of the base point, P an even multiple, - * due to the choice of precomputed points in the modified comb method. - * So branches for these cases do not leak secret information. - * - * We accept Q->Z being unset (saving memory in tables) as meaning 1. - * - * Cost: 1A := 8M + 3S - */ -static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) -{ - int ret; - mbedtls_mpi T1, T2, T3, T4, X, Y, Z; - -#if defined(MBEDTLS_SELF_TEST) - add_count++; -#endif - -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_add_mixed( grp, R, P, Q ); - } -#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ - - /* - * Trivial cases: P == 0 or Q == 0 (case 1) - */ - if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) - return( mbedtls_ecp_copy( R, Q ) ); - - if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) - return( mbedtls_ecp_copy( R, P ) ); - - /* - * Make sure Q coordinates are normalized - */ - if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); - mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); - - /* Special cases (2) and (3) */ - if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) - { - if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) - { - ret = ecp_double_jac( grp, R, P ); - goto cleanup; - } - else - { - ret = mbedtls_ecp_set_zero( R ); - goto cleanup; - } - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); - -cleanup: - - mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); - mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); - - return( ret ); -} - -/* - * Randomize jacobian coordinates: - * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l - * This is sort of the reverse operation of ecp_normalize_jac(). - * - * This countermeasure was first suggested in [2]. - */ -static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret; - mbedtls_mpi l, ll; - size_t p_size; - int count = 0; - -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ); - } -#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ - - p_size = ( grp->pbits + 7 ) / 8; - mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); - - /* Generate l such that 1 < l < p */ - do - { - mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ); - - while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); - - /* Z = l * Z */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); - - /* X = l^2 * X */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); - - /* Y = l^3 * Y */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); - -cleanup: - mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); - - return( ret ); -} - -/* - * Check and define parameters used by the comb method (see below for details) - */ -#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 -#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" -#endif - -/* d = ceil( n / w ) */ -#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 - -/* number of precomputed points */ -#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) - -/* - * Compute the representation of m that will be used with our comb method. - * - * The basic comb method is described in GECC 3.44 for example. We use a - * modified version that provides resistance to SPA by avoiding zero - * digits in the representation as in [3]. We modify the method further by - * requiring that all K_i be odd, which has the small cost that our - * representation uses one more K_i, due to carries. - * - * Also, for the sake of compactness, only the seven low-order bits of x[i] - * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in - * the paper): it is set if and only if if s_i == -1; - * - * Calling conventions: - * - x is an array of size d + 1 - * - w is the size, ie number of teeth, of the comb, and must be between - * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) - * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d - * (the result will be incorrect if these assumptions are not satisfied) - */ -static void ecp_comb_fixed( unsigned char x[], size_t d, - unsigned char w, const mbedtls_mpi *m ) -{ - size_t i, j; - unsigned char c, cc, adjust; - - memset( x, 0, d+1 ); - - /* First get the classical comb values (except for x_d = 0) */ - for( i = 0; i < d; i++ ) - for( j = 0; j < w; j++ ) - x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; - - /* Now make sure x_1 .. x_d are odd */ - c = 0; - for( i = 1; i <= d; i++ ) - { - /* Add carry and update it */ - cc = x[i] & c; - x[i] = x[i] ^ c; - c = cc; - - /* Adjust if needed, avoiding branches */ - adjust = 1 - ( x[i] & 0x01 ); - c |= x[i] & ( x[i-1] * adjust ); - x[i] = x[i] ^ ( x[i-1] * adjust ); - x[i-1] |= adjust << 7; - } -} - -/* - * Precompute points for the comb method - * - * If i = i_{w-1} ... i_1 is the binary representation of i, then - * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P - * - * T must be able to hold 2^{w - 1} elements - * - * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) - */ -static int ecp_precompute_comb( const mbedtls_ecp_group *grp, - mbedtls_ecp_point T[], const mbedtls_ecp_point *P, - unsigned char w, size_t d ) -{ - int ret; - unsigned char i, k; - size_t j; - mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; - - /* - * Set T[0] = P and - * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); - - k = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) - { - cur = T + i; - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); - for( j = 0; j < d; j++ ) - MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); - - TT[k++] = cur; - } - - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); - - /* - * Compute the remaining ones using the minimal number of additions - * Be careful to update T[2^l] only after using it! - */ - k = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) - { - j = i; - while( j-- ) - { - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); - TT[k++] = &T[i + j]; - } - } - - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); - -cleanup: - - return( ret ); -} - -/* - * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] - */ -static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, - unsigned char i ) -{ - int ret; - unsigned char ii, j; - - /* Ignore the "sign" bit and scale down */ - ii = ( i & 0x7Fu ) >> 1; - - /* Read the whole table to thwart cache-based timing attacks */ - for( j = 0; j < t_len; j++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); - } - - /* Safely invert result if i is "negative" */ - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); - -cleanup: - return( ret ); -} - -/* - * Core multiplication algorithm for the (modified) comb method. - * This part is actually common with the basic comb method (GECC 3.44) - * - * Cost: d A + d D + 1 R - */ -static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, - const unsigned char x[], size_t d, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point Txi; - size_t i; - - mbedtls_ecp_point_init( &Txi ); - - /* Start with a non-zero point and randomize its coordinates */ - i = d; - MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); - if( f_rng != 0 ) - MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); - - while( i-- != 0 ) - { - MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); - MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); - } - -cleanup: - - mbedtls_ecp_point_free( &Txi ); - - return( ret ); -} - -/* - * Multiplication using the comb method, - * for curves in short Weierstrass form - */ -static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char w, m_is_odd, p_eq_g, pre_len, i; - size_t d; - unsigned char k[COMB_MAX_D + 1]; - mbedtls_ecp_point *T; - mbedtls_mpi M, mm; - - mbedtls_mpi_init( &M ); - mbedtls_mpi_init( &mm ); - - /* we need N to be odd to trnaform m in an odd number, check now */ - if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Minimize the number of multiplications, that is minimize - * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) - * (see costs of the various parts, with 1S = 1M) - */ - w = grp->nbits >= 384 ? 5 : 4; - - /* - * If P == G, pre-compute a bit more, since this may be re-used later. - * Just adding one avoids upping the cost of the first mul too much, - * and the memory cost too. - */ -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 - p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && - mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); - if( p_eq_g ) - w++; -#else - p_eq_g = 0; -#endif - - /* - * Make sure w is within bounds. - * (The last test is useful only for very small curves in the test suite.) - */ - if( w > MBEDTLS_ECP_WINDOW_SIZE ) - w = MBEDTLS_ECP_WINDOW_SIZE; - if( w >= grp->nbits ) - w = 2; - - /* Other sizes that depend on w */ - pre_len = 1U << ( w - 1 ); - d = ( grp->nbits + w - 1 ) / w; - - /* - * Prepare precomputed points: if P == G we want to - * use grp->T if already initialized, or initialize it. - */ - T = p_eq_g ? grp->T : NULL; - - if( T == NULL ) - { - T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); - if( T == NULL ) - { - ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; - goto cleanup; - } - - MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); - - if( p_eq_g ) - { - grp->T = T; - grp->T_size = pre_len; - } - } - - /* - * Make sure M is odd (M = m or M = N - m, since N is odd) - * using the fact that m * P = - (N - m) * P - */ - m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); - - /* - * Go for comb multiplication, R = M * P - */ - ecp_comb_fixed( k, d, w, &M ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); - - /* - * Now get m * P from M * P and normalize it - */ - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); - -cleanup: - - if( T != NULL && ! p_eq_g ) - { - for( i = 0; i < pre_len; i++ ) - mbedtls_ecp_point_free( &T[i] ); - mbedtls_free( T ); - } - - mbedtls_mpi_free( &M ); - mbedtls_mpi_free( &mm ); - - if( ret != 0 ) - mbedtls_ecp_point_free( R ); - - return( ret ); -} - -#endif /* ECP_SHORTWEIERSTRASS */ - -#if defined(ECP_MONTGOMERY) -/* - * For Montgomery curves, we do all the internal arithmetic in projective - * coordinates. Import/export of points uses only the x coordinates, which is - * internaly represented as X / Z. - * - * For scalar multiplication, we'll use a Montgomery ladder. - */ - -/* - * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 - * Cost: 1M + 1I - */ -static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) -{ - int ret; - -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_mxz( grp, P ); - } -#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ - - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); - -cleanup: - return( ret ); -} - -/* - * Randomize projective x/z coordinates: - * (X, Z) -> (l X, l Z) for random l - * This is sort of the reverse operation of ecp_normalize_mxz(). - * - * This countermeasure was first suggested in [2]. - * Cost: 2M - */ -static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret; - mbedtls_mpi l; - size_t p_size; - int count = 0; - -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); - } -#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ - - p_size = ( grp->pbits + 7 ) / 8; - mbedtls_mpi_init( &l ); - - /* Generate l such that 1 < l < p */ - do - { - mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ); - - while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); - -cleanup: - mbedtls_mpi_free( &l ); - - return( ret ); -} - -/* - * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), - * for Montgomery curves in x/z coordinates. - * - * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 - * with - * d = X1 - * P = (X2, Z2) - * Q = (X3, Z3) - * R = (X4, Z4) - * S = (X5, Z5) - * and eliminating temporary variables tO, ..., t4. - * - * Cost: 5M + 4S - */ -static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, mbedtls_ecp_point *S, - const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, - const mbedtls_mpi *d ) -{ - int ret; - mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; - -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ); - } -#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ - - mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); - mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); - mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); - -cleanup: - mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); - mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); - mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); - - return( ret ); -} - -/* - * Multiplication with Montgomery ladder in x/z coordinates, - * for curves in Montgomery form - */ -static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t i; - unsigned char b; - mbedtls_ecp_point RP; - mbedtls_mpi PX; - - mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); - - /* Save PX and read from P before writing to R, in case P == R */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); - - /* Set R to zero in modified x/z coordinates */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); - mbedtls_mpi_free( &R->Y ); - - /* RP.X might be sligtly larger than P, so reduce it */ - MOD_ADD( RP.X ); - - /* Randomize coordinates of the starting point */ - if( f_rng != NULL ) - MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); - - /* Loop invariant: R = result so far, RP = R + P */ - i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ - while( i-- > 0 ) - { - b = mbedtls_mpi_get_bit( m, i ); - /* - * if (b) R = 2R + P else R = 2R, - * which is: - * if (b) double_add( RP, R, RP, R ) - * else double_add( R, RP, R, RP ) - * but using safe conditional swaps to avoid leaks - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); - MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); - } - - MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); - -cleanup: - mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); - - return( ret ); -} - -#endif /* ECP_MONTGOMERY */ - -/* - * Multiplication R = m * P - */ -int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - char is_grp_capable = 0; -#endif - - /* Common sanity checks */ - if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || - ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_ECP_INTERNAL_ALT) -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &mbedtls_threading_ecp_mutex ) != 0 ) - return ( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - -#endif - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) - { - MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); - } - -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ); - -#endif -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng ); - -#endif -#if defined(MBEDTLS_ECP_INTERNAL_ALT) -cleanup: - - if ( is_grp_capable ) - { - mbedtls_internal_ecp_free( grp ); - } - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &mbedtls_threading_ecp_mutex ) != 0 ) - return ( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - -#endif -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - return( ret ); -} - -#if defined(ECP_SHORTWEIERSTRASS) -/* - * Check that an affine point is valid as a public key, - * short weierstrass curves (SEC1 3.2.3.1) - */ -static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) -{ - int ret; - mbedtls_mpi YY, RHS; - - /* pt coordinates must be normalized for our checks */ - if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || - mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || - mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || - mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - - mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); - - /* - * YY = Y^2 - * RHS = X (X^2 + A) + B = X^3 + A X + B - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); - - /* Special case for A = -3 */ - if( grp->A.p == NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); - - if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) - ret = MBEDTLS_ERR_ECP_INVALID_KEY; - -cleanup: - - mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); - - return( ret ); -} -#endif /* ECP_SHORTWEIERSTRASS */ - -/* - * R = m * P with shortcuts for m == 1 and m == -1 - * NOT constant-time - ONLY for short Weierstrass! - */ -static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, - const mbedtls_mpi *m, - const mbedtls_ecp_point *P ) -{ - int ret; - - if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); - } - else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); - if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); - } - -cleanup: - return( ret ); -} - -/* - * Linear combination - * NOT constant-time - */ -int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) -{ - int ret; - mbedtls_ecp_point mP; -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - char is_grp_capable = 0; -#endif - - if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - - mbedtls_ecp_point_init( &mP ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); - -#if defined(MBEDTLS_ECP_INTERNAL_ALT) -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &mbedtls_threading_ecp_mutex ) != 0 ) - return ( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - -#endif - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) - { - MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); - } - -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); - -cleanup: - -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable ) - { - mbedtls_internal_ecp_free( grp ); - } - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &mbedtls_threading_ecp_mutex ) != 0 ) - return ( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - -#endif -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - mbedtls_ecp_point_free( &mP ); - - return( ret ); -} - - -#if defined(ECP_MONTGOMERY) -/* - * Check validity of a public key for Montgomery curves with x-only schemes - */ -static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) -{ - /* [Curve25519 p. 5] Just check X is the correct number of bytes */ - if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - - return( 0 ); -} -#endif /* ECP_MONTGOMERY */ - -/* - * Check that a point is valid as a public key - */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) -{ - /* Must use affine coordinates */ - if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - return( ecp_check_pubkey_mx( grp, pt ) ); -#endif -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - return( ecp_check_pubkey_sw( grp, pt ) ); -#endif - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); -} - -/* - * Check that an mbedtls_mpi is valid as a private key - */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) -{ -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - { - /* see [Curve25519] page 5 */ - if( mbedtls_mpi_get_bit( d, 0 ) != 0 || - mbedtls_mpi_get_bit( d, 1 ) != 0 || - mbedtls_mpi_get_bit( d, 2 ) != 0 || - mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - else - return( 0 ); - } -#endif /* ECP_MONTGOMERY */ -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - { - /* see SEC1 3.2 */ - if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - else - return( 0 ); - } -#endif /* ECP_SHORTWEIERSTRASS */ - - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); -} - -/* - * Generate a keypair with configurable base point - */ -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t n_size = ( grp->nbits + 7 ) / 8; - -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - { - /* [M225] page 5 */ - size_t b; - - do { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); - } while( mbedtls_mpi_bitlen( d ) == 0); - - /* Make sure the most significant bit is nbits */ - b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ - if( b > grp->nbits ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); - else - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); - - /* Make sure the last three bits are unset */ - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); - } - else -#endif /* ECP_MONTGOMERY */ -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - { - /* SEC1 3.2.1: Generate d such that 1 <= n < N */ - int count = 0; - unsigned char rnd[MBEDTLS_ECP_MAX_BYTES]; - - /* - * Match the procedure given in RFC 6979 (deterministic ECDSA): - * - use the same byte ordering; - * - keep the leftmost nbits bits of the generated octet string; - * - try until result is in the desired range. - * This also avoids any biais, which is especially important for ECDSA. - */ - do - { - MBEDTLS_MPI_CHK( f_rng( p_rng, rnd, n_size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); - - /* - * Each try has at worst a probability 1/2 of failing (the msb has - * a probability 1/2 of being 0, and then the result will be < N), - * so after 30 tries failure probability is a most 2**(-30). - * - * For most curves, 1 try is enough with overwhelming probability, - * since N starts with a lot of 1s in binary, but some curves - * such as secp224k1 are actually very close to the worst case. - */ - if( ++count > 30 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); - } - else -#endif /* ECP_SHORTWEIERSTRASS */ - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - -cleanup: - if( ret != 0 ) - return( ret ); - - return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); -} - -/* - * Generate key pair, wrapper for conventional base point - */ -int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); -} - -/* - * Generate a keypair, prettier wrapper - */ -int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret; - - if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) - return( ret ); - - return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); -} - -/* - * Check a public-private key pair - */ -int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) -{ - int ret; - mbedtls_ecp_point Q; - mbedtls_ecp_group grp; - - if( pub->grp.id == MBEDTLS_ECP_DP_NONE || - pub->grp.id != prv->grp.id || - mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || - mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || - mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) - { - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - } - - mbedtls_ecp_point_init( &Q ); - mbedtls_ecp_group_init( &grp ); - - /* mbedtls_ecp_mul() needs a non-const group... */ - mbedtls_ecp_group_copy( &grp, &prv->grp ); - - /* Also checks d is valid */ - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); - - if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || - mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || - mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - -cleanup: - mbedtls_ecp_point_free( &Q ); - mbedtls_ecp_group_free( &grp ); - - return( ret ); -} - -#if defined(MBEDTLS_SELF_TEST) - -/* - * Checkup routine - */ -int mbedtls_ecp_self_test( int verbose ) -{ - int ret; - size_t i; - mbedtls_ecp_group grp; - mbedtls_ecp_point R, P; - mbedtls_mpi m; - unsigned long add_c_prev, dbl_c_prev, mul_c_prev; - /* exponents especially adapted for secp192r1 */ - const char *exponents[] = - { - "000000000000000000000000000000000000000000000001", /* one */ - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ - "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ - "400000000000000000000000000000000000000000000000", /* one and zeros */ - "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ - "555555555555555555555555555555555555555555555555", /* 101010... */ - }; - - mbedtls_ecp_group_init( &grp ); - mbedtls_ecp_point_init( &R ); - mbedtls_ecp_point_init( &P ); - mbedtls_mpi_init( &m ); - - /* Use secp192r1 if available, or any available curve */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); -#else - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); -#endif - - if( verbose != 0 ) - mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); - - /* Do a dummy multiplication first to trigger precomputation */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); - - add_count = 0; - dbl_count = 0; - mul_count = 0; - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); - - for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) - { - add_c_prev = add_count; - dbl_c_prev = dbl_count; - mul_c_prev = mul_count; - add_count = 0; - dbl_count = 0; - mul_count = 0; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); - - if( add_count != add_c_prev || - dbl_count != dbl_c_prev || - mul_count != mul_c_prev ) - { - if( verbose != 0 ) - mbedtls_printf( "failed (%u)\n", (unsigned int) i ); - - ret = 1; - goto cleanup; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); - /* We computed P = 2G last time, use it */ - - add_count = 0; - dbl_count = 0; - mul_count = 0; - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); - - for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) - { - add_c_prev = add_count; - dbl_c_prev = dbl_count; - mul_c_prev = mul_count; - add_count = 0; - dbl_count = 0; - mul_count = 0; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); - - if( add_count != add_c_prev || - dbl_count != dbl_c_prev || - mul_count != mul_c_prev ) - { - if( verbose != 0 ) - mbedtls_printf( "failed (%u)\n", (unsigned int) i ); - - ret = 1; - goto cleanup; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - - if( ret < 0 && verbose != 0 ) - mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); - - mbedtls_ecp_group_free( &grp ); - mbedtls_ecp_point_free( &R ); - mbedtls_ecp_point_free( &P ); - mbedtls_mpi_free( &m ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* !MBEDTLS_ECP_ALT */ - -#endif /* MBEDTLS_ECP_C */ diff --git a/components/security/mbedtls/src/ecp_curves.c b/components/security/mbedtls/src/ecp_curves.c deleted file mode 100644 index df5ac3ee..00000000 --- a/components/security/mbedtls/src/ecp_curves.c +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * Elliptic curves over GF(p): curve-specific data and 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_ECP_C) - -#include "mbedtls/ecp.h" - -#include - -#if !defined(MBEDTLS_ECP_ALT) - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -/* - * Conversion macros for embedded constants: - * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 - */ -#if defined(MBEDTLS_HAVE_INT32) - -#define BYTES_TO_T_UINT_4( a, b, c, d ) \ - ( (mbedtls_mpi_uint) a << 0 ) | \ - ( (mbedtls_mpi_uint) b << 8 ) | \ - ( (mbedtls_mpi_uint) c << 16 ) | \ - ( (mbedtls_mpi_uint) d << 24 ) - -#define BYTES_TO_T_UINT_2( a, b ) \ - BYTES_TO_T_UINT_4( a, b, 0, 0 ) - -#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ - BYTES_TO_T_UINT_4( a, b, c, d ), \ - BYTES_TO_T_UINT_4( e, f, g, h ) - -#else /* 64-bits */ - -#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ - ( (mbedtls_mpi_uint) a << 0 ) | \ - ( (mbedtls_mpi_uint) b << 8 ) | \ - ( (mbedtls_mpi_uint) c << 16 ) | \ - ( (mbedtls_mpi_uint) d << 24 ) | \ - ( (mbedtls_mpi_uint) e << 32 ) | \ - ( (mbedtls_mpi_uint) f << 40 ) | \ - ( (mbedtls_mpi_uint) g << 48 ) | \ - ( (mbedtls_mpi_uint) h << 56 ) - -#define BYTES_TO_T_UINT_4( a, b, c, d ) \ - BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) - -#define BYTES_TO_T_UINT_2( a, b ) \ - BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) - -#endif /* bits in mbedtls_mpi_uint */ - -/* - * Note: the constants are in little-endian order - * to be directly usable in MPIs - */ - -/* - * Domain parameters for secp192r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -static const mbedtls_mpi_uint secp192r1_p[] = { - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp192r1_b[] = { - BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), - BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), - BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), -}; -static const mbedtls_mpi_uint secp192r1_gx[] = { - BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), - BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), - BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), -}; -static const mbedtls_mpi_uint secp192r1_gy[] = { - BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), - BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), - BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), -}; -static const mbedtls_mpi_uint secp192r1_n[] = { - BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), - BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -/* - * Domain parameters for secp224r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -static const mbedtls_mpi_uint secp224r1_p[] = { - BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), -}; -static const mbedtls_mpi_uint secp224r1_b[] = { - BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), - BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), - BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), - BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), -}; -static const mbedtls_mpi_uint secp224r1_gx[] = { - BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), - BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), - BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), - BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), -}; -static const mbedtls_mpi_uint secp224r1_gy[] = { - BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), - BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), - BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), - BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), -}; -static const mbedtls_mpi_uint secp224r1_n[] = { - BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), - BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -/* - * Domain parameters for secp256r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -static const mbedtls_mpi_uint secp256r1_p[] = { - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp256r1_b[] = { - BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), - BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), - BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), - BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), -}; -static const mbedtls_mpi_uint secp256r1_gx[] = { - BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), - BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), - BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), - BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), -}; -static const mbedtls_mpi_uint secp256r1_gy[] = { - BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), - BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), - BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), - BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), -}; -static const mbedtls_mpi_uint secp256r1_n[] = { - BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), - BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -/* - * Domain parameters for secp384r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -static const mbedtls_mpi_uint secp384r1_p[] = { - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp384r1_b[] = { - BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), - BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), - BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), - BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), - BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), - BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), -}; -static const mbedtls_mpi_uint secp384r1_gx[] = { - BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), - BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), - BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), - BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), - BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), - BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), -}; -static const mbedtls_mpi_uint secp384r1_gy[] = { - BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), - BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), - BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), - BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), - BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), - BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), -}; -static const mbedtls_mpi_uint secp384r1_n[] = { - BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), - BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), - BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -/* - * Domain parameters for secp521r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -static const mbedtls_mpi_uint secp521r1_p[] = { - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_2( 0xFF, 0x01 ), -}; -static const mbedtls_mpi_uint secp521r1_b[] = { - BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), - BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), - BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), - BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), - BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), - BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), - BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), - BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), - BYTES_TO_T_UINT_2( 0x51, 0x00 ), -}; -static const mbedtls_mpi_uint secp521r1_gx[] = { - BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), - BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), - BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), - BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), - BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), - BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), - BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), - BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), - BYTES_TO_T_UINT_2( 0xC6, 0x00 ), -}; -static const mbedtls_mpi_uint secp521r1_gy[] = { - BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), - BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), - BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), - BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), - BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), - BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), - BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), - BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), - BYTES_TO_T_UINT_2( 0x18, 0x01 ), -}; -static const mbedtls_mpi_uint secp521r1_n[] = { - BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), - BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), - BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), - BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), - BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_2( 0xFF, 0x01 ), -}; -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -static const mbedtls_mpi_uint secp192k1_p[] = { - BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp192k1_a[] = { - BYTES_TO_T_UINT_2( 0x00, 0x00 ), -}; -static const mbedtls_mpi_uint secp192k1_b[] = { - BYTES_TO_T_UINT_2( 0x03, 0x00 ), -}; -static const mbedtls_mpi_uint secp192k1_gx[] = { - BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), - BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), - BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), -}; -static const mbedtls_mpi_uint secp192k1_gy[] = { - BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), - BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), - BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), -}; -static const mbedtls_mpi_uint secp192k1_n[] = { - BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), - BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -static const mbedtls_mpi_uint secp224k1_p[] = { - BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp224k1_a[] = { - BYTES_TO_T_UINT_2( 0x00, 0x00 ), -}; -static const mbedtls_mpi_uint secp224k1_b[] = { - BYTES_TO_T_UINT_2( 0x05, 0x00 ), -}; -static const mbedtls_mpi_uint secp224k1_gx[] = { - BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), - BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), - BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), - BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), -}; -static const mbedtls_mpi_uint secp224k1_gy[] = { - BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), - BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), - BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), - BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), -}; -static const mbedtls_mpi_uint secp224k1_n[] = { - BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), - BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), -}; -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -static const mbedtls_mpi_uint secp256k1_p[] = { - BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp256k1_a[] = { - BYTES_TO_T_UINT_2( 0x00, 0x00 ), -}; -static const mbedtls_mpi_uint secp256k1_b[] = { - BYTES_TO_T_UINT_2( 0x07, 0x00 ), -}; -static const mbedtls_mpi_uint secp256k1_gx[] = { - BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), - BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), - BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), - BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), -}; -static const mbedtls_mpi_uint secp256k1_gy[] = { - BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), - BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), - BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), - BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), -}; -static const mbedtls_mpi_uint secp256k1_n[] = { - BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), - BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), - BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -/* - * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) - */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP256r1_p[] = { - BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), - BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), - BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), - BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_a[] = { - BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), - BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), - BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), - BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_b[] = { - BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), - BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), - BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), - BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { - BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), - BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), - BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), - BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { - BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), - BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), - BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), - BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_n[] = { - BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), - BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), - BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), - BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), -}; -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ - -/* - * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) - */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP384r1_p[] = { - BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), - BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), - BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), - BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), - BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), - BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_a[] = { - BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), - BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), - BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), - BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), - BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), - BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_b[] = { - BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), - BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), - BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), - BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), - BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), - BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { - BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), - BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), - BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), - BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), - BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), - BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { - BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), - BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), - BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), - BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), - BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), - BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_n[] = { - BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), - BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), - BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), - BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), - BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), - BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), -}; -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ - -/* - * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) - */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP512r1_p[] = { - BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), - BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), - BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), - BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), - BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), - BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), - BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), - BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_a[] = { - BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), - BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), - BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), - BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), - BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), - BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), - BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), - BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_b[] = { - BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), - BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), - BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), - BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), - BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), - BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), - BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), - BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { - BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), - BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), - BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), - BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), - BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), - BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), - BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), - BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { - BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), - BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), - BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), - BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), - BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), - BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), - BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), - BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_n[] = { - BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), - BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), - BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), - BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), - BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), - BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), - BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), - BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), -}; -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - -/* - * Create an MPI from embedded constants - * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) - */ -static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) -{ - X->s = 1; - X->n = len / sizeof( mbedtls_mpi_uint ); - X->p = (mbedtls_mpi_uint *) p; -} - -/* - * Set an MPI to static value 1 - */ -static inline void ecp_mpi_set1( mbedtls_mpi *X ) -{ - static mbedtls_mpi_uint one[] = { 1 }; - X->s = 1; - X->n = 1; - X->p = one; -} - -/* - * Make group available from embedded constants - */ -static int ecp_group_load( mbedtls_ecp_group *grp, - const mbedtls_mpi_uint *p, size_t plen, - const mbedtls_mpi_uint *a, size_t alen, - const mbedtls_mpi_uint *b, size_t blen, - const mbedtls_mpi_uint *gx, size_t gxlen, - const mbedtls_mpi_uint *gy, size_t gylen, - const mbedtls_mpi_uint *n, size_t nlen) -{ - ecp_mpi_load( &grp->P, p, plen ); - if( a != NULL ) - ecp_mpi_load( &grp->A, a, alen ); - ecp_mpi_load( &grp->B, b, blen ); - ecp_mpi_load( &grp->N, n, nlen ); - - ecp_mpi_load( &grp->G.X, gx, gxlen ); - ecp_mpi_load( &grp->G.Y, gy, gylen ); - ecp_mpi_set1( &grp->G.Z ); - - grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - grp->nbits = mbedtls_mpi_bitlen( &grp->N ); - - grp->h = 1; - - return( 0 ); -} - -#if defined(MBEDTLS_ECP_NIST_OPTIM) -/* Forward declarations */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -static int ecp_mod_p192( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -static int ecp_mod_p224( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -static int ecp_mod_p256( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -static int ecp_mod_p384( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -static int ecp_mod_p521( mbedtls_mpi * ); -#endif - -#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; -#else -#define NIST_MODP( P ) -#endif /* MBEDTLS_ECP_NIST_OPTIM */ - -/* Additional forward declarations */ -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -static int ecp_mod_p255( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -static int ecp_mod_p192k1( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -static int ecp_mod_p224k1( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -static int ecp_mod_p256k1( mbedtls_mpi * ); -#endif - -#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ - G ## _p, sizeof( G ## _p ), \ - G ## _a, sizeof( G ## _a ), \ - G ## _b, sizeof( G ## _b ), \ - G ## _gx, sizeof( G ## _gx ), \ - G ## _gy, sizeof( G ## _gy ), \ - G ## _n, sizeof( G ## _n ) ) - -#define LOAD_GROUP( G ) ecp_group_load( grp, \ - G ## _p, sizeof( G ## _p ), \ - NULL, 0, \ - G ## _b, sizeof( G ## _b ), \ - G ## _gx, sizeof( G ## _gx ), \ - G ## _gy, sizeof( G ## _gy ), \ - G ## _n, sizeof( G ## _n ) ) - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -/* - * Specialized function for creating the Curve25519 group - */ -static int ecp_use_curve25519( mbedtls_ecp_group *grp ) -{ - int ret; - - /* Actually ( A + 2 ) / 4 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); - - /* P = 2^255 - 19 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); - grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - - /* Y intentionaly not set, since we use x/z coordinates. - * This is used as a marker to identify Montgomery curves! */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); - mbedtls_mpi_free( &grp->G.Y ); - - /* Actually, the required msb for private keys */ - grp->nbits = 254; - -cleanup: - if( ret != 0 ) - mbedtls_ecp_group_free( grp ); - - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - -/* - * Set a group using well-known domain parameters - */ -int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) -{ - mbedtls_ecp_group_free( grp ); - - grp->id = id; - - switch( id ) - { -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - case MBEDTLS_ECP_DP_SECP192R1: - NIST_MODP( p192 ); - return( LOAD_GROUP( secp192r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - case MBEDTLS_ECP_DP_SECP224R1: - NIST_MODP( p224 ); - return( LOAD_GROUP( secp224r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - case MBEDTLS_ECP_DP_SECP256R1: - NIST_MODP( p256 ); - return( LOAD_GROUP( secp256r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - case MBEDTLS_ECP_DP_SECP384R1: - NIST_MODP( p384 ); - return( LOAD_GROUP( secp384r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - case MBEDTLS_ECP_DP_SECP521R1: - NIST_MODP( p521 ); - return( LOAD_GROUP( secp521r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - case MBEDTLS_ECP_DP_SECP192K1: - grp->modp = ecp_mod_p192k1; - return( LOAD_GROUP_A( secp192k1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - case MBEDTLS_ECP_DP_SECP224K1: - grp->modp = ecp_mod_p224k1; - return( LOAD_GROUP_A( secp224k1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - case MBEDTLS_ECP_DP_SECP256K1: - grp->modp = ecp_mod_p256k1; - return( LOAD_GROUP_A( secp256k1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - case MBEDTLS_ECP_DP_BP256R1: - return( LOAD_GROUP_A( brainpoolP256r1 ) ); -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - case MBEDTLS_ECP_DP_BP384R1: - return( LOAD_GROUP_A( brainpoolP384r1 ) ); -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - case MBEDTLS_ECP_DP_BP512R1: - return( LOAD_GROUP_A( brainpoolP512r1 ) ); -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - case MBEDTLS_ECP_DP_CURVE25519: - grp->modp = ecp_mod_p255; - return( ecp_use_curve25519( grp ) ); -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - - default: - mbedtls_ecp_group_free( grp ); - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - } -} - -#if defined(MBEDTLS_ECP_NIST_OPTIM) -/* - * Fast reduction modulo the primes used by the NIST curves. - * - * These functions are critical for speed, but not needed for correct - * operations. So, we make the choice to heavily rely on the internals of our - * bignum library, which creates a tight coupling between these functions and - * our MPI implementation. However, the coupling between the ECP module and - * MPI remains loose, since these functions can be deactivated at will. - */ - -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -/* - * Compared to the way things are presented in FIPS 186-3 D.2, - * we proceed in columns, from right (least significant chunk) to left, - * adding chunks to N in place, and keeping a carry for the next chunk. - * This avoids moving things around in memory, and uselessly adding zeros, - * compared to the more straightforward, line-oriented approach. - * - * For this prime we need to handle data in chunks of 64 bits. - * Since this is always a multiple of our basic mbedtls_mpi_uint, we can - * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. - */ - -/* Add 64-bit chunks (dst += src) and update carry */ -static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) -{ - unsigned char i; - mbedtls_mpi_uint c = 0; - for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) - { - *dst += c; c = ( *dst < c ); - *dst += *src; c += ( *dst < *src ); - } - *carry += c; -} - -/* Add carry to a 64-bit chunk and update carry */ -static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) -{ - unsigned char i; - for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) - { - *dst += *carry; - *carry = ( *dst < *carry ); - } -} - -#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) -#define A( i ) N->p + i * WIDTH -#define ADD( i ) add64( p, A( i ), &c ) -#define NEXT p += WIDTH; carry64( p, &c ) -#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 - -/* - * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) - */ -static int ecp_mod_p192( mbedtls_mpi *N ) -{ - int ret; - mbedtls_mpi_uint c = 0; - mbedtls_mpi_uint *p, *end; - - /* Make sure we have enough blocks so that A(5) is legal */ - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); - - p = N->p; - end = p + N->n; - - ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 - ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 - ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 - -cleanup: - return( ret ); -} - -#undef WIDTH -#undef A -#undef ADD -#undef NEXT -#undef LAST -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -/* - * The reader is advised to first understand ecp_mod_p192() since the same - * general structure is used here, but with additional complications: - * (1) chunks of 32 bits, and (2) subtractions. - */ - -/* - * For these primes, we need to handle data in chunks of 32 bits. - * This makes it more complicated if we use 64 bits limbs in MPI, - * which prevents us from using a uniform access method as for p192. - * - * So, we define a mini abstraction layer to access 32 bit chunks, - * load them in 'cur' for work, and store them back from 'cur' when done. - * - * While at it, also define the size of N in terms of 32-bit chunks. - */ -#define LOAD32 cur = A( i ); - -#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ - -#define MAX32 N->n -#define A( j ) N->p[j] -#define STORE32 N->p[i] = cur; - -#else /* 64-bit */ - -#define MAX32 N->n * 2 -#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] ) -#define STORE32 \ - if( i % 2 ) { \ - N->p[i/2] &= 0x00000000FFFFFFFF; \ - N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ - } else { \ - N->p[i/2] &= 0xFFFFFFFF00000000; \ - N->p[i/2] |= (mbedtls_mpi_uint) cur; \ - } - -#endif /* sizeof( mbedtls_mpi_uint ) */ - -/* - * Helpers for addition and subtraction of chunks, with signed carry. - */ -static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) -{ - *dst += src; - *carry += ( *dst < src ); -} - -static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) -{ - *carry -= ( *dst < src ); - *dst -= src; -} - -#define ADD( j ) add32( &cur, A( j ), &c ); -#define SUB( j ) sub32( &cur, A( j ), &c ); - -/* - * Helpers for the main 'loop' - * (see fix_negative for the motivation of C) - */ -#define INIT( b ) \ - int ret; \ - signed char c = 0, cc; \ - uint32_t cur; \ - size_t i = 0, bits = b; \ - mbedtls_mpi C; \ - mbedtls_mpi_uint Cp[ b / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ - \ - C.s = 1; \ - C.n = b / 8 / sizeof( mbedtls_mpi_uint) + 1; \ - C.p = Cp; \ - memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ - \ - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, b * 2 / 8 / sizeof( mbedtls_mpi_uint ) ) ); \ - LOAD32; - -#define NEXT \ - STORE32; i++; LOAD32; \ - cc = c; c = 0; \ - if( cc < 0 ) \ - sub32( &cur, -cc, &c ); \ - else \ - add32( &cur, cc, &c ); \ - -#define LAST \ - STORE32; i++; \ - cur = c > 0 ? c : 0; STORE32; \ - cur = 0; while( ++i < MAX32 ) { STORE32; } \ - if( c < 0 ) fix_negative( N, c, &C, bits ); - -/* - * If the result is negative, we get it in the form - * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' - */ -static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) -{ - int ret; - - /* C = - c * 2^(bits + 32) */ -#if !defined(MBEDTLS_HAVE_INT64) - ((void) bits); -#else - if( bits == 224 ) - C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; - else -#endif - C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; - - /* N = - ( C - N ) */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); - N->s = -1; - -cleanup: - - return( ret ); -} - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -/* - * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) - */ -static int ecp_mod_p224( mbedtls_mpi *N ) -{ - INIT( 224 ); - - SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 - SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 - SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 - SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 - SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 - SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 - SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -/* - * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) - */ -static int ecp_mod_p256( mbedtls_mpi *N ) -{ - INIT( 256 ); - - ADD( 8 ); ADD( 9 ); - SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 - - ADD( 9 ); ADD( 10 ); - SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 - - ADD( 10 ); ADD( 11 ); - SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 - - ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); - SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 - - ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); - SUB( 9 ); SUB( 10 ); NEXT; // A4 - - ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); - SUB( 10 ); SUB( 11 ); NEXT; // A5 - - ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); - SUB( 8 ); SUB( 9 ); NEXT; // A6 - - ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); - SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -/* - * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) - */ -static int ecp_mod_p384( mbedtls_mpi *N ) -{ - INIT( 384 ); - - ADD( 12 ); ADD( 21 ); ADD( 20 ); - SUB( 23 ); NEXT; // A0 - - ADD( 13 ); ADD( 22 ); ADD( 23 ); - SUB( 12 ); SUB( 20 ); NEXT; // A2 - - ADD( 14 ); ADD( 23 ); - SUB( 13 ); SUB( 21 ); NEXT; // A2 - - ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); - SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 - - ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); - SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 - - ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); - SUB( 16 ); NEXT; // A5 - - ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); - SUB( 17 ); NEXT; // A6 - - ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); - SUB( 18 ); NEXT; // A7 - - ADD( 20 ); ADD( 17 ); ADD( 16 ); - SUB( 19 ); NEXT; // A8 - - ADD( 21 ); ADD( 18 ); ADD( 17 ); - SUB( 20 ); NEXT; // A9 - - ADD( 22 ); ADD( 19 ); ADD( 18 ); - SUB( 21 ); NEXT; // A10 - - ADD( 23 ); ADD( 20 ); ADD( 19 ); - SUB( 22 ); LAST; // A11 - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#undef A -#undef LOAD32 -#undef STORE32 -#undef MAX32 -#undef INIT -#undef NEXT -#undef LAST - -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || - MBEDTLS_ECP_DP_SECP256R1_ENABLED || - MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -/* - * Here we have an actual Mersenne prime, so things are more straightforward. - * However, chunks are aligned on a 'weird' boundary (521 bits). - */ - -/* Size of p521 in terms of mbedtls_mpi_uint */ -#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) - -/* Bits to keep in the most significant mbedtls_mpi_uint */ -#define P521_MASK 0x01FF - -/* - * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) - * Write N as A1 + 2^521 A0, return A0 + A1 - */ -static int ecp_mod_p521( mbedtls_mpi *N ) -{ - int ret; - size_t i; - mbedtls_mpi M; - mbedtls_mpi_uint Mp[P521_WIDTH + 1]; - /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: - * we need to hold bits 513 to 1056, which is 34 limbs, that is - * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ - - if( N->n < P521_WIDTH ) - return( 0 ); - - /* M = A1 */ - M.s = 1; - M.n = N->n - ( P521_WIDTH - 1 ); - if( M.n > P521_WIDTH + 1 ) - M.n = P521_WIDTH + 1; - M.p = Mp; - memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); - - /* N = A0 */ - N->p[P521_WIDTH - 1] &= P521_MASK; - for( i = P521_WIDTH; i < N->n; i++ ) - N->p[i] = 0; - - /* N = A0 + A1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); - -cleanup: - return( ret ); -} - -#undef P521_WIDTH -#undef P521_MASK -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#endif /* MBEDTLS_ECP_NIST_OPTIM */ - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - -/* Size of p255 in terms of mbedtls_mpi_uint */ -#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) - -/* - * Fast quasi-reduction modulo p255 = 2^255 - 19 - * Write N as A0 + 2^255 A1, return A0 + 19 * A1 - */ -static int ecp_mod_p255( mbedtls_mpi *N ) -{ - int ret; - size_t i; - mbedtls_mpi M; - mbedtls_mpi_uint Mp[P255_WIDTH + 2]; - - if( N->n < P255_WIDTH ) - return( 0 ); - - /* M = A1 */ - M.s = 1; - M.n = N->n - ( P255_WIDTH - 1 ); - if( M.n > P255_WIDTH + 1 ) - M.n = P255_WIDTH + 1; - M.p = Mp; - memset( Mp, 0, sizeof Mp ); - memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); - M.n++; /* Make room for multiplication by 19 */ - - /* N = A0 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); - for( i = P255_WIDTH; i < N->n; i++ ) - N->p[i] = 0; - - /* N = A0 + 19 * A1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -/* - * Fast quasi-reduction modulo P = 2^s - R, - * with R about 33 bits, used by the Koblitz curves. - * - * Write N as A0 + 2^224 A1, return A0 + R * A1. - * Actually do two passes, since R is big. - */ -#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P -#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R -static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, - size_t adjust, size_t shift, mbedtls_mpi_uint mask ) -{ - int ret; - size_t i; - mbedtls_mpi M, R; - mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; - - if( N->n < p_limbs ) - return( 0 ); - - /* Init R */ - R.s = 1; - R.p = Rp; - R.n = P_KOBLITZ_R; - - /* Common setup for M */ - M.s = 1; - M.p = Mp; - - /* M = A1 */ - M.n = N->n - ( p_limbs - adjust ); - if( M.n > p_limbs + adjust ) - M.n = p_limbs + adjust; - memset( Mp, 0, sizeof Mp ); - memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); - if( shift != 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); - M.n += R.n; /* Make room for multiplication by R */ - - /* N = A0 */ - if( mask != 0 ) - N->p[p_limbs - 1] &= mask; - for( i = p_limbs; i < N->n; i++ ) - N->p[i] = 0; - - /* N = A0 + R * A1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); - - /* Second pass */ - - /* M = A1 */ - M.n = N->n - ( p_limbs - adjust ); - if( M.n > p_limbs + adjust ) - M.n = p_limbs + adjust; - memset( Mp, 0, sizeof Mp ); - memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); - if( shift != 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); - M.n += R.n; /* Make room for multiplication by R */ - - /* N = A0 */ - if( mask != 0 ) - N->p[p_limbs - 1] &= mask; - for( i = p_limbs; i < N->n; i++ ) - N->p[i] = 0; - - /* N = A0 + R * A1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || - MBEDTLS_ECP_DP_SECP224K1_ENABLED) || - MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -/* - * Fast quasi-reduction modulo p192k1 = 2^192 - R, - * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 - */ -static int ecp_mod_p192k1( mbedtls_mpi *N ) -{ - static mbedtls_mpi_uint Rp[] = { - BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; - - return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); -} -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -/* - * Fast quasi-reduction modulo p224k1 = 2^224 - R, - * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 - */ -static int ecp_mod_p224k1( mbedtls_mpi *N ) -{ - static mbedtls_mpi_uint Rp[] = { - BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; - -#if defined(MBEDTLS_HAVE_INT64) - return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); -#else - return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); -#endif -} - -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -/* - * Fast quasi-reduction modulo p256k1 = 2^256 - R, - * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 - */ -static int ecp_mod_p256k1( mbedtls_mpi *N ) -{ - static mbedtls_mpi_uint Rp[] = { - BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; - return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); -} -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -#endif /* !MBEDTLS_ECP_ALT */ - -#endif /* MBEDTLS_ECP_C */ diff --git a/components/security/mbedtls/src/entropy.c b/components/security/mbedtls/src/entropy.c deleted file mode 100644 index fce66506..00000000 --- a/components/security/mbedtls/src/entropy.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Entropy accumulator implementation - * - * Copyright (C) 2006-2016, 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" -#include -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ENTROPY_C) - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) -#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " -#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " -#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " -#endif - -#include "mbedtls/entropy.h" -#include "mbedtls/entropy_poll.h" - -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#include "mbedtls/platform.h" -#endif - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if defined(MBEDTLS_HAVEGE_C) -#include "mbedtls/havege.h" -#endif - -/* 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; -} - -#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ - -void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) -{ - memset( ctx, 0, sizeof(mbedtls_entropy_context) ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif - -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_starts( &ctx->accumulator, 0 ); -#else - mbedtls_sha256_starts( &ctx->accumulator, 0 ); -#endif -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_init( &ctx->havege_data ); -#endif - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) - mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, - 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif - -#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) -#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) - mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, - MBEDTLS_ENTROPY_MIN_PLATFORM, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif -#if defined(MBEDTLS_TIMING_C) - - mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, - MBEDTLS_ENTROPY_MIN_HARDCLOCK, - MBEDTLS_ENTROPY_SOURCE_WEAK ); -#endif -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, - MBEDTLS_ENTROPY_MIN_HAVEGE, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, - MBEDTLS_ENTROPY_MIN_HARDWARE, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif -#if defined(MBEDTLS_ENTROPY_NV_SEED) - mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, - MBEDTLS_ENTROPY_BLOCK_SIZE, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif -#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ -} - -void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) -{ -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_free( &ctx->havege_data ); -#endif -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); -} - -int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, - mbedtls_entropy_f_source_ptr f_source, void *p_source, - size_t threshold, int strong ) -{ - int index, ret = 0; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - index = ctx->source_count; - if( index >= MBEDTLS_ENTROPY_MAX_SOURCES ) - { - ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; - goto exit; - } - - ctx->source[index].f_source = f_source; - ctx->source[index].p_source = p_source; - ctx->source[index].threshold = threshold; - ctx->source[index].strong = strong; - - ctx->source_count++; - -exit: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Entropy accumulator update - */ -static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, - const unsigned char *data, size_t len ) -{ - unsigned char header[2]; - unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; - size_t use_len = len; - const unsigned char *p = data; - - if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) - { -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512( data, len, tmp, 0 ); -#else - mbedtls_sha256( data, len, tmp, 0 ); -#endif - p = tmp; - use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; - } - - header[0] = source_id; - header[1] = use_len & 0xFF; - -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_update( &ctx->accumulator, header, 2 ); - mbedtls_sha512_update( &ctx->accumulator, p, use_len ); -#else - mbedtls_sha256_update( &ctx->accumulator, header, 2 ); - mbedtls_sha256_update( &ctx->accumulator, p, use_len ); -#endif - - return( 0 ); -} - -int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, - const unsigned char *data, size_t len ) -{ - int ret; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Run through the different sources to add entropy to our accumulator - */ -static int entropy_gather_internal( mbedtls_entropy_context *ctx ) -{ - int ret, i, have_one_strong = 0; - unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; - size_t olen; - - if( ctx->source_count == 0 ) - return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); - - /* - * Run through our entropy sources - */ - for( i = 0; i < ctx->source_count; i++ ) - { - if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) - have_one_strong = 1; - - olen = 0; - if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, - buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) - { - return( ret ); - } - - /* - * Add if we actually gathered something - */ - if( olen > 0 ) - { - entropy_update( ctx, (unsigned char) i, buf, olen ); - ctx->source[i].size += olen; - } - } - - if( have_one_strong == 0 ) - return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ); - - return( 0 ); -} - -/* - * Thread-safe wrapper for entropy_gather_internal() - */ -int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) -{ - int ret; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - ret = entropy_gather_internal( ctx ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) -{ - int ret, count = 0, i, done; - mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; - - if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - -#if defined(MBEDTLS_ENTROPY_NV_SEED) - /* Update the NV entropy seed before generating any entropy for outside - * use. - */ - if( ctx->initial_entropy_run == 0 ) - { - ctx->initial_entropy_run = 1; - if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) - return( ret ); - } -#endif - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - /* - * Always gather extra entropy before a call - */ - do - { - if( count++ > ENTROPY_MAX_LOOP ) - { - ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; - goto exit; - } - - if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) - goto exit; - - done = 1; - for( i = 0; i < ctx->source_count; i++ ) - if( ctx->source[i].size < ctx->source[i].threshold ) - done = 0; - } - while( ! done ); - - memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); - -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_finish( &ctx->accumulator, buf ); - - /* - * Reset accumulator and counters and recycle existing entropy - */ - memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); - mbedtls_sha512_starts( &ctx->accumulator, 0 ); - mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - /* - * Perform second SHA-512 on entropy - */ - mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); -#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ - mbedtls_sha256_finish( &ctx->accumulator, buf ); - - /* - * Reset accumulator and counters and recycle existing entropy - */ - memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); - mbedtls_sha256_starts( &ctx->accumulator, 0 ); - mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - /* - * Perform second SHA-256 on entropy - */ - mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); -#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ - - for( i = 0; i < ctx->source_count; i++ ) - ctx->source[i].size = 0; - - memcpy( output, buf, len ); - - ret = 0; - -exit: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) -{ - int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; - unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; - - /* Read new seed and write it to NV */ - if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) - return( ret ); - - if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - - /* Manually update the remaining stream with a separator value to diverge */ - memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); - mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - return( 0 ); -} -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#if defined(MBEDTLS_FS_IO) -#if 0 -int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) -{ - int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; - FILE *f; - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; - - if( ( f = fopen( path, "wb" ) ) == NULL ) - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - - if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) - goto exit; - - if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) - { - ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; - goto exit; - } - - ret = 0; - -exit: - fclose( f ); - return( ret ); -} - -int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) -{ - FILE *f; - size_t n; - unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) - n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; - - if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - } - - fclose( f ); - - mbedtls_entropy_update_manual( ctx, buf, n ); - - return( mbedtls_entropy_write_seed_file( ctx, path ) ); -} -#endif -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_SELF_TEST) -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) -/* - * Dummy source function - */ -static int entropy_dummy_source( void *data, unsigned char *output, - size_t len, size_t *olen ) -{ - ((void) data); - - memset( output, 0x2a, len ); - *olen = len; - - return( 0 ); -} -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - -static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) -{ - int ret = 0; - size_t entropy_len = 0; - size_t olen = 0; - size_t attempts = buf_len; - - while( attempts > 0 && entropy_len < buf_len ) - { - if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, - buf_len - entropy_len, &olen ) ) != 0 ) - return( ret ); - - entropy_len += olen; - attempts--; - } - - if( entropy_len < buf_len ) - { - ret = 1; - } - - return( ret ); -} - - -static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, - size_t buf_len ) -{ - unsigned char set= 0xFF; - unsigned char unset = 0x00; - size_t i; - - for( i = 0; i < buf_len; i++ ) - { - set &= buf[i]; - unset |= buf[i]; - } - - return( set == 0xFF || unset == 0x00 ); -} - -/* - * A test to ensure hat the entropy sources are functioning correctly - * and there is no obvious failure. The test performs the following checks: - * - The entropy source is not providing only 0s (all bits unset) or 1s (all - * bits set). - * - The entropy source is not providing values in a pattern. Because the - * hardware could be providing data in an arbitrary length, this check polls - * the hardware entropy source twice and compares the result to ensure they - * are not equal. - * - The error code returned by the entropy source is not an error. - */ -int mbedtls_entropy_source_self_test( int verbose ) -{ - int ret = 0; - unsigned char buf0[2 * sizeof( unsigned long long int )]; - unsigned char buf1[2 * sizeof( unsigned long long int )]; - - if( verbose != 0 ) - mbedtls_printf( " ENTROPY_BIAS test: " ); - - memset( buf0, 0x00, sizeof( buf0 ) ); - memset( buf1, 0x00, sizeof( buf1 ) ); - - if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) - goto cleanup; - if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) - goto cleanup; - - /* Make sure that the returned values are not all 0 or 1 */ - if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) - goto cleanup; - if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) - goto cleanup; - - /* Make sure that the entropy source is not returning values in a - * pattern */ - ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; - -cleanup: - if( verbose != 0 ) - { - if( ret != 0 ) - mbedtls_printf( "failed\n" ); - else - mbedtls_printf( "passed\n" ); - - mbedtls_printf( "\n" ); - } - - return( ret != 0 ); -} - -#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ - -/* - * The actual entropy quality is hard to test, but we can at least - * test that the functions don't cause errors and write the correct - * amount of data to buffers. - */ -int mbedtls_entropy_self_test( int verbose ) -{ - int ret = 1; -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) - mbedtls_entropy_context ctx; - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; - unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; - size_t i, j; -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ - - if( verbose != 0 ) - mbedtls_printf( " ENTROPY test: " ); - -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) - mbedtls_entropy_init( &ctx ); - - /* First do a gather to make sure we have default sources */ - if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) - goto cleanup; - - ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, - MBEDTLS_ENTROPY_SOURCE_WEAK ); - if( ret != 0 ) - goto cleanup; - - if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) - goto cleanup; - - /* - * To test that mbedtls_entropy_func writes correct number of bytes: - * - use the whole buffer and rely on ASan to detect overruns - * - collect entropy 8 times and OR the result in an accumulator: - * any byte should then be 0 with probably 2^(-64), so requiring - * each of the 32 or 64 bytes to be non-zero has a false failure rate - * of at most 2^(-58) which is acceptable. - */ - for( i = 0; i < 8; i++ ) - { - if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) - goto cleanup; - - for( j = 0; j < sizeof( buf ); j++ ) - acc[j] |= buf[j]; - } - - for( j = 0; j < sizeof( buf ); j++ ) - { - if( acc[j] == 0 ) - { - ret = 1; - goto cleanup; - } - } - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) - goto cleanup; -#endif - -cleanup: - mbedtls_entropy_free( &ctx ); -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ - - if( verbose != 0 ) - { - if( ret != 0 ) - mbedtls_printf( "failed\n" ); - else - mbedtls_printf( "passed\n" ); - - mbedtls_printf( "\n" ); - } - - return( ret != 0 ); -} -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_ENTROPY_C */ diff --git a/components/security/mbedtls/src/entropy_poll.c b/components/security/mbedtls/src/entropy_poll.c deleted file mode 100644 index 120883e5..00000000 --- a/components/security/mbedtls/src/entropy_poll.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2016, 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_ENTROPY_C) - -#include "mbedtls/entropy.h" -#include "mbedtls/entropy_poll.h" - -#if defined(MBEDTLS_TIMING_C) -#include -#include "mbedtls/timing.h" -#endif -#if defined(MBEDTLS_HAVEGE_C) -#include "mbedtls/havege.h" -#endif -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#include "mbedtls/platform.h" -#endif - -#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) - -#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) -//#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - -#if !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0400 -#endif -#include -#include - -int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, - size_t *olen ) -{ - HCRYPTPROV provider; - ((void) data); - *olen = 0; - - if( CryptAcquireContext( &provider, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) - { - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - } - - if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) - { - CryptReleaseContext( provider, 0 ); - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - } - - CryptReleaseContext( provider, 0 ); - *olen = len; - - return( 0 ); -} -#else /* _WIN32 && !EFIX64 && !EFI32 */ - -/* - * Test for Linux getrandom() support. - * Since there is no wrapper in the libc yet, use the generic syscall wrapper - * available in GNU libc and compatible libc's (eg uClibc). - */ -#if defined(__linux__) && defined(__GLIBC__) -#include -#include -#if defined(SYS_getrandom) -#define HAVE_GETRANDOM - -static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) -{ - /* MemSan cannot understand that the syscall writes to the buffer */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) - memset( buf, 0, buflen ); -#endif -#endif - - return( syscall( SYS_getrandom, buf, buflen, flags ) ); -} - -#include -/* Check if version is at least 3.17.0 */ -static int check_version_3_17_plus( void ) -{ - int minor; - struct utsname un; - const char *ver; - - /* Get version information */ - uname(&un); - ver = un.release; - - /* Check major version; assume a single digit */ - if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) - return( -1 ); - - if( ver[0] - '0' > 3 ) - return( 0 ); - - /* Ok, so now we know major == 3, check minor. - * Assume 1 or 2 digits. */ - if( ver[2] < '0' || ver[2] > '9' ) - return( -1 ); - - minor = ver[2] - '0'; - - if( ver[3] >= '0' && ver[3] <= '9' ) - minor = 10 * minor + ver[3] - '0'; - else if( ver [3] != '.' ) - return( -1 ); - - if( minor < 17 ) - return( -1 ); - - return( 0 ); -} -static int has_getrandom = -1; -#endif /* SYS_getrandom */ -#endif /* __linux__ */ - -#include -extern int bl_rand(); -int mbedtls_platform_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - // FILE *file; - // size_t read_len; - ((void) data); - size_t i; - *olen = 0; - unsigned int rand_buf = 0; -#if defined(HAVE_GETRANDOM) - if( has_getrandom == -1 ) - has_getrandom = ( check_version_3_17_plus() == 0 ); - - if( has_getrandom ) - { - int ret; - - if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - *olen = ret; - return( 0 ); - } -#endif /* HAVE_GETRANDOM */ - - // file = fopen( "/dev/urandom", "rb" ); - // if( file == NULL ) - // return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - // read_len = fread( output, 1, len, file ); - // if( read_len != len ) - // { - // fclose( file ); - // return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - // } - - // fclose( file ); - for(i = 0;i < len;i++) { - if(0 == (i % 4)) { - rand_buf = bl_rand(); - } - output[i] = rand_buf & 0xff; - rand_buf = rand_buf >> 8; - } - *olen = len; - - return( 0 ); -} -#endif /* _WIN32 && !EFIX64 && !EFI32 */ -#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) -int mbedtls_null_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - ((void) data); - ((void) output); - *olen = 0; - - if( len < sizeof(unsigned char) ) - return( 0 ); - - *olen = sizeof(unsigned char); - - return( 0 ); -} -#endif - -#if defined(MBEDTLS_TIMING_C) -int mbedtls_hardclock_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - unsigned long timer = mbedtls_timing_hardclock(); - ((void) data); - *olen = 0; - - if( len < sizeof(unsigned long) ) - return( 0 ); - - memcpy( output, &timer, sizeof(unsigned long) ); - *olen = sizeof(unsigned long); - - return( 0 ); -} -#endif /* MBEDTLS_TIMING_C */ - -#if defined(MBEDTLS_HAVEGE_C) -int mbedtls_havege_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - mbedtls_havege_state *hs = (mbedtls_havege_state *) data; - *olen = 0; - - if( mbedtls_havege_random( hs, output, len ) != 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - *olen = len; - - return( 0 ); -} -#endif /* MBEDTLS_HAVEGE_C */ - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -int mbedtls_nv_seed_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; - size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; - ((void) data); - - memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - if( len < use_len ) - use_len = len; - - memcpy( output, buf, use_len ); - *olen = use_len; - - return( 0 ); -} -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#endif /* MBEDTLS_ENTROPY_C */ diff --git a/components/security/mbedtls/src/error.c b/components/security/mbedtls/src/error.c deleted file mode 100644 index dd2db0c4..00000000 --- a/components/security/mbedtls/src/error.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - * Error message information - * - * 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_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) -#include "mbedtls/error.h" -#include -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_snprintf snprintf -#define mbedtls_time_t time_t -#endif - -#if defined(MBEDTLS_ERROR_C) - -#include - -#if defined(MBEDTLS_AES_C) -#include "mbedtls/aes.h" -#endif - -#if defined(MBEDTLS_BASE64_C) -#include "mbedtls/base64.h" -#endif - -#if defined(MBEDTLS_BIGNUM_C) -#include "mbedtls/bignum.h" -#endif - -#if defined(MBEDTLS_BLOWFISH_C) -#include "mbedtls/blowfish.h" -#endif - -#if defined(MBEDTLS_CAMELLIA_C) -#include "mbedtls/camellia.h" -#endif - -#if defined(MBEDTLS_CCM_C) -#include "mbedtls/ccm.h" -#endif - -#if defined(MBEDTLS_CIPHER_C) -#include "mbedtls/cipher.h" -#endif - -#if defined(MBEDTLS_CTR_DRBG_C) -#include "mbedtls/ctr_drbg.h" -#endif - -#if defined(MBEDTLS_DES_C) -#include "mbedtls/des.h" -#endif - -#if defined(MBEDTLS_DHM_C) -#include "mbedtls/dhm.h" -#endif - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ENTROPY_C) -#include "mbedtls/entropy.h" -#endif - -#if defined(MBEDTLS_GCM_C) -#include "mbedtls/gcm.h" -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) -#include "mbedtls/hmac_drbg.h" -#endif - -#if defined(MBEDTLS_MD_C) -#include "mbedtls/md.h" -#endif - -#if defined(MBEDTLS_NET_C) -#include "mbedtls/net_sockets.h" -#endif - -#if defined(MBEDTLS_OID_C) -#include "mbedtls/oid.h" -#endif - -#if defined(MBEDTLS_PADLOCK_C) -#include "mbedtls/padlock.h" -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/pk.h" -#endif - -#if defined(MBEDTLS_PKCS12_C) -#include "mbedtls/pkcs12.h" -#endif - -#if defined(MBEDTLS_PKCS5_C) -#include "mbedtls/pkcs5.h" -#endif - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) -#include "mbedtls/ssl.h" -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -#include "mbedtls/x509.h" -#endif - -#if defined(MBEDTLS_XTEA_C) -#include "mbedtls/xtea.h" -#endif - - -void mbedtls_strerror( int ret, char *buf, size_t buflen ) -{ - size_t len; - int use_ret; - - if( buflen == 0 ) - return; - - memset( buf, 0x00, buflen ); - - if( ret < 0 ) - ret = -ret; - - if( ret & 0xFF80 ) - { - use_ret = ret & 0xFF80; - - // High level error codes - // - // BEGIN generated code -#if defined(MBEDTLS_CIPHER_C) - if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) - mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid, eg because it was free()ed" ); -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_DHM_C) - if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Making of the public value failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); - if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "DHM - Read/write of file failed" ); -#endif /* MBEDTLS_DHM_C */ - -#if defined(MBEDTLS_ECP_C) - if( use_ret == -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); - if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "ECP - Requested curve not available" ); - if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); - if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); - if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); - if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) - mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); - if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_MD_C) - if( use_ret == -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "MD - The selected feature is not available" ); - if( use_ret == -(MBEDTLS_ERR_MD_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "MD - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_MD_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); - if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); -#endif /* MBEDTLS_MD_C */ - -#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) - if( use_ret == -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) - mbedtls_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); - if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_DATA) ) - mbedtls_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); - if( use_ret == -(MBEDTLS_ERR_PEM_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); - if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_ENC_IV) ) - mbedtls_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); - if( use_ret == -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG) ) - mbedtls_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); - if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); - if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); - if( use_ret == -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); - if( use_ret == -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); -#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ - -#if defined(MBEDTLS_PK_C) - if( use_ret == -(MBEDTLS_ERR_PK_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "PK - Memory allocation failed" ); - if( use_ret == -(MBEDTLS_ERR_PK_TYPE_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); - if( use_ret == -(MBEDTLS_ERR_PK_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "PK - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_PK_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "PK - Read/write of file failed" ); - if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION) ) - mbedtls_snprintf( buf, buflen, "PK - Unsupported key version" ); - if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "PK - Invalid key tag or value" ); - if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG) ) - mbedtls_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); - if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "PK - Private key password can't be empty" ); - if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); - if( use_ret == -(MBEDTLS_ERR_PK_INVALID_PUBKEY) ) - mbedtls_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); - if( use_ret == -(MBEDTLS_ERR_PK_INVALID_ALG) ) - mbedtls_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE) ) - mbedtls_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); - if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); - if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); -#endif /* MBEDTLS_PK_C */ - -#if defined(MBEDTLS_PKCS12_C) - if( use_ret == -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); - if( use_ret == -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); - if( use_ret == -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); -#endif /* MBEDTLS_PKCS12_C */ - -#if defined(MBEDTLS_PKCS5_C) - if( use_ret == -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); - if( use_ret == -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); - if( use_ret == -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); -#endif /* MBEDTLS_PKCS5_C */ - -#if defined(MBEDTLS_RSA_C) - if( use_ret == -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_RSA_INVALID_PADDING) ) - mbedtls_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); - if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); - if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the library's validity check" ); - if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); - if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - The private key operation failed" ); - if( use_ret == -(MBEDTLS_ERR_RSA_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); - if( use_ret == -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ) - mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); - if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_SSL_TLS_C) - if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) - mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) - mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) - mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); - if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) - mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) - mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) - mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) - mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) - mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); - if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); - if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) - mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); - if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) - { - mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); - return; - } - if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) - mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) - mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); - if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) - mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); - if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) - mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); - if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) - mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) - mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) - mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) - mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); - if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) - mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) - mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" ); - if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) - mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); - if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) - mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) - mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); - if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) - mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) - mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); - if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) - mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); -#endif /* MBEDTLS_SSL_TLS_C */ - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) - if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); - if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) - mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) - mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) - mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) - mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) - mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) - mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) - mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) - mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) - mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); - if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) - mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); - if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); - if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); - if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) - mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); - if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); - if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); - if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); -#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ - // END generated code - - if( strlen( buf ) == 0 ) - mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); - } - - use_ret = ret & ~0xFF80; - - if( use_ret == 0 ) - return; - - // If high level code is present, make a concatenation between both - // error strings. - // - len = strlen( buf ); - - if( len > 0 ) - { - if( buflen - len < 5 ) - return; - - mbedtls_snprintf( buf + len, buflen - len, " : " ); - - buf += len + 3; - buflen -= len + 3; - } - - // Low level error codes - // - // BEGIN generated code -#if defined(MBEDTLS_AES_C) - if( use_ret == -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); - if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_ASN1_PARSE_C) - if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) ) - mbedtls_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_LENGTH) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); -#endif /* MBEDTLS_ASN1_PARSE_C */ - -#if defined(MBEDTLS_BASE64_C) - if( use_ret == -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "BASE64 - Output buffer too small" ); - if( use_ret == -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER) ) - mbedtls_snprintf( buf, buflen, "BASE64 - Invalid character in input" ); -#endif /* MBEDTLS_BASE64_C */ - -#if defined(MBEDTLS_BIGNUM_C) - if( use_ret == -(MBEDTLS_ERR_MPI_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); - if( use_ret == -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_MPI_INVALID_CHARACTER) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); - if( use_ret == -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); - if( use_ret == -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); - if( use_ret == -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); - if( use_ret == -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); - if( use_ret == -(MBEDTLS_ERR_MPI_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); -#endif /* MBEDTLS_BIGNUM_C */ - -#if defined(MBEDTLS_BLOWFISH_C) - if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); - if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); -#endif /* MBEDTLS_BLOWFISH_C */ - -#if defined(MBEDTLS_CAMELLIA_C) - if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); - if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_CCM_C) - if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) - mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) - mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); -#endif /* MBEDTLS_CCM_C */ - -#if defined(MBEDTLS_CTR_DRBG_C) - if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); - if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" ); - if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); - if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" ); -#endif /* MBEDTLS_CTR_DRBG_C */ - -#if defined(MBEDTLS_DES_C) - if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ENTROPY_C) - if( use_ret == -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); - if( use_ret == -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); - if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); - if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - No strong sources have been added to poll" ); - if( use_ret == -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); -#endif /* MBEDTLS_ENTROPY_C */ - -#if defined(MBEDTLS_GCM_C) - if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) - mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); - if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) - mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_HMAC_DRBG_C) - if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); - if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); - if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); - if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) - mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); -#endif /* MBEDTLS_HMAC_DRBG_C */ - -#if defined(MBEDTLS_NET_C) - if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); - if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); - if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); - if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) - mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); - if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) - mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); - if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); - if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) - mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); -#endif /* MBEDTLS_NET_C */ - -#if defined(MBEDTLS_OID_C) - if( use_ret == -(MBEDTLS_ERR_OID_NOT_FOUND) ) - mbedtls_snprintf( buf, buflen, "OID - OID is not found" ); - if( use_ret == -(MBEDTLS_ERR_OID_BUF_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "OID - output buffer is too small" ); -#endif /* MBEDTLS_OID_C */ - -#if defined(MBEDTLS_PADLOCK_C) - if( use_ret == -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED) ) - mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); -#endif /* MBEDTLS_PADLOCK_C */ - -#if defined(MBEDTLS_THREADING_C) - if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); - if( use_ret == -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_THREADING_MUTEX_ERROR) ) - mbedtls_snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); -#endif /* MBEDTLS_THREADING_C */ - -#if defined(MBEDTLS_XTEA_C) - if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); -#endif /* MBEDTLS_XTEA_C */ - // END generated code - - if( strlen( buf ) != 0 ) - return; - - mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); -} - -#else /* MBEDTLS_ERROR_C */ - -#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) - -/* - * Provide an non-function in case MBEDTLS_ERROR_C is not defined - */ -void mbedtls_strerror( int ret, char *buf, size_t buflen ) -{ - ((void) ret); - - if( buflen > 0 ) - buf[0] = '\0'; -} - -#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ - -#endif /* MBEDTLS_ERROR_C */ diff --git a/components/security/mbedtls/src/gcm.c b/components/security/mbedtls/src/gcm.c deleted file mode 100644 index f1210c52..00000000 --- a/components/security/mbedtls/src/gcm.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - * NIST SP800-38D compliant GCM implementation - * - * 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) - */ - -/* - * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf - * - * See also: - * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf - * - * We use the algorithm described as Shoup's method with 4-bit tables in - * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_GCM_C) - -#include "mbedtls/gcm.h" - -#include - -#if defined(MBEDTLS_AESNI_C) -#include "mbedtls/aesni.h" -#endif - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* 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; -} - -/* - * Initialize a context - */ -void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); -} - -/* - * Precompute small multiples of H, that is set - * HH[i] || HL[i] = H times i, - * where i is seen as a field element as in [MGV], ie high-order bits - * correspond to low powers of P. The result is stored in the same way, that - * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL - * corresponds to P^127. - */ -static int gcm_gen_table( mbedtls_gcm_context *ctx ) -{ - int ret, i, j; - uint64_t hi, lo; - uint64_t vl, vh; - unsigned char h[16]; - size_t olen = 0; - - memset( h, 0, 16 ); - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) - return( ret ); - - /* pack h as two 64-bits ints, big-endian */ - GET_UINT32_BE( hi, h, 0 ); - GET_UINT32_BE( lo, h, 4 ); - vh = (uint64_t) hi << 32 | lo; - - GET_UINT32_BE( hi, h, 8 ); - GET_UINT32_BE( lo, h, 12 ); - vl = (uint64_t) hi << 32 | lo; - - /* 8 = 1000 corresponds to 1 in GF(2^128) */ - ctx->HL[8] = vl; - ctx->HH[8] = vh; - -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - /* With CLMUL support, we need only h, not the rest of the table */ - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) - return( 0 ); -#endif - - /* 0 corresponds to 0 in GF(2^128) */ - ctx->HH[0] = 0; - ctx->HL[0] = 0; - - for( i = 4; i > 0; i >>= 1 ) - { - uint32_t T = ( vl & 1 ) * 0xe1000000U; - vl = ( vh << 63 ) | ( vl >> 1 ); - vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); - - ctx->HL[i] = vl; - ctx->HH[i] = vh; - } - - for( i = 2; i <= 8; i *= 2 ) - { - uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; - vh = *HiH; - vl = *HiL; - for( j = 1; j < i; j++ ) - { - HiH[j] = vh ^ ctx->HH[j]; - HiL[j] = vl ^ ctx->HL[j]; - } - } - - return( 0 ); -} - -int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - - cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - - if( cipher_info->block_size != 16 ) - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - - mbedtls_cipher_free( &ctx->cipher_ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = gcm_gen_table( ctx ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Shoup's method for multiplication use this table with - * last4[x] = x times P^128 - * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] - */ -static const uint64_t last4[16] = -{ - 0x0000, 0x1c20, 0x3840, 0x2460, - 0x7080, 0x6ca0, 0x48c0, 0x54e0, - 0xe100, 0xfd20, 0xd940, 0xc560, - 0x9180, 0x8da0, 0xa9c0, 0xb5e0 -}; - -/* - * Sets output to x times H using the precomputed tables. - * x and output are seen as elements of GF(2^128) as in [MGV]. - */ -static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], - unsigned char output[16] ) -{ - int i = 0; - unsigned char lo, hi, rem; - uint64_t zh, zl; - -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { - unsigned char h[16]; - - PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); - PUT_UINT32_BE( ctx->HH[8], h, 4 ); - PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); - PUT_UINT32_BE( ctx->HL[8], h, 12 ); - - mbedtls_aesni_gcm_mult( output, x, h ); - return; - } -#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ - - lo = x[15] & 0xf; - - zh = ctx->HH[lo]; - zl = ctx->HL[lo]; - - for( i = 15; i >= 0; i-- ) - { - lo = x[i] & 0xf; - hi = x[i] >> 4; - - if( i != 15 ) - { - rem = (unsigned char) zl & 0xf; - zl = ( zh << 60 ) | ( zl >> 4 ); - zh = ( zh >> 4 ); - zh ^= (uint64_t) last4[rem] << 48; - zh ^= ctx->HH[lo]; - zl ^= ctx->HL[lo]; - - } - - rem = (unsigned char) zl & 0xf; - zl = ( zh << 60 ) | ( zl >> 4 ); - zh = ( zh >> 4 ); - zh ^= (uint64_t) last4[rem] << 48; - zh ^= ctx->HH[hi]; - zl ^= ctx->HL[hi]; - } - - PUT_UINT32_BE( zh >> 32, output, 0 ); - PUT_UINT32_BE( zh, output, 4 ); - PUT_UINT32_BE( zl >> 32, output, 8 ); - PUT_UINT32_BE( zl, output, 12 ); -} - -int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, - int mode, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len ) -{ - int ret; - unsigned char work_buf[16]; - size_t i; - const unsigned char *p; - size_t use_len, olen = 0; - - /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ - if( ( (uint64_t) iv_len ) >> 61 != 0 || - ( (uint64_t) add_len ) >> 61 != 0 ) - { - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - } - - memset( ctx->y, 0x00, sizeof(ctx->y) ); - memset( ctx->buf, 0x00, sizeof(ctx->buf) ); - - ctx->mode = mode; - ctx->len = 0; - ctx->add_len = 0; - - if( iv_len == 12 ) - { - memcpy( ctx->y, iv, iv_len ); - ctx->y[15] = 1; - } - else - { - memset( work_buf, 0x00, 16 ); - PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); - - p = iv; - while( iv_len > 0 ) - { - use_len = ( iv_len < 16 ) ? iv_len : 16; - - for( i = 0; i < use_len; i++ ) - ctx->y[i] ^= p[i]; - - gcm_mult( ctx, ctx->y, ctx->y ); - - iv_len -= use_len; - p += use_len; - } - - for( i = 0; i < 16; i++ ) - ctx->y[i] ^= work_buf[i]; - - gcm_mult( ctx, ctx->y, ctx->y ); - } - - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, - &olen ) ) != 0 ) - { - return( ret ); - } - - ctx->add_len = add_len; - p = add; - while( add_len > 0 ) - { - use_len = ( add_len < 16 ) ? add_len : 16; - - for( i = 0; i < use_len; i++ ) - ctx->buf[i] ^= p[i]; - - gcm_mult( ctx, ctx->buf, ctx->buf ); - - add_len -= use_len; - p += use_len; - } - - return( 0 ); -} - -int mbedtls_gcm_update( mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - unsigned char ectr[16]; - size_t i; - const unsigned char *p; - unsigned char *out_p = output; - size_t use_len, olen = 0; - - if( output > input && (size_t) ( output - input ) < length ) - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - - /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes - * Also check for possible overflow */ - if( ctx->len + length < ctx->len || - (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) - { - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - } - - ctx->len += length; - - p = input; - while( length > 0 ) - { - use_len = ( length < 16 ) ? length : 16; - - for( i = 16; i > 12; i-- ) - if( ++ctx->y[i - 1] != 0 ) - break; - - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, - &olen ) ) != 0 ) - { - return( ret ); - } - - for( i = 0; i < use_len; i++ ) - { - if( ctx->mode == MBEDTLS_GCM_DECRYPT ) - ctx->buf[i] ^= p[i]; - out_p[i] = ectr[i] ^ p[i]; - if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) - ctx->buf[i] ^= out_p[i]; - } - - gcm_mult( ctx, ctx->buf, ctx->buf ); - - length -= use_len; - p += use_len; - out_p += use_len; - } - - return( 0 ); -} - -int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, - unsigned char *tag, - size_t tag_len ) -{ - unsigned char work_buf[16]; - size_t i; - uint64_t orig_len = ctx->len * 8; - uint64_t orig_add_len = ctx->add_len * 8; - - if( tag_len > 16 || tag_len < 4 ) - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - - memcpy( tag, ctx->base_ectr, tag_len ); - - if( orig_len || orig_add_len ) - { - memset( work_buf, 0x00, 16 ); - - PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); - PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); - PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); - PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); - - for( i = 0; i < 16; i++ ) - ctx->buf[i] ^= work_buf[i]; - - gcm_mult( ctx, ctx->buf, ctx->buf ); - - for( i = 0; i < tag_len; i++ ) - tag[i] ^= ctx->buf[i]; - } - - return( 0 ); -} - -int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, - int mode, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *input, - unsigned char *output, - size_t tag_len, - unsigned char *tag ) -{ - int ret; - - if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *tag, - size_t tag_len, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - unsigned char check_tag[16]; - size_t i; - int diff; - - if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, - iv, iv_len, add, add_len, - input, output, tag_len, check_tag ) ) != 0 ) - { - return( ret ); - } - - /* Check tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) - { - mbedtls_zeroize( output, length ); - return( MBEDTLS_ERR_GCM_AUTH_FAILED ); - } - - return( 0 ); -} - -void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) -{ - mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); -} - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -/* - * AES-GCM test vectors from: - * - * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip - */ -#define MAX_TESTS 6 - -static const int key_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 1 }; - -static const unsigned char key[MAX_TESTS][32] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, - 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, -}; - -static const size_t iv_len[MAX_TESTS] = - { 12, 12, 12, 12, 8, 60 }; - -static const int iv_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 2 }; - -static const unsigned char iv[MAX_TESTS][64] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, - 0xde, 0xca, 0xf8, 0x88 }, - { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, - 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, - 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, - 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, - 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, - 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, - 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, - 0xa6, 0x37, 0xb3, 0x9b }, -}; - -static const size_t add_len[MAX_TESTS] = - { 0, 0, 0, 20, 20, 20 }; - -static const int add_index[MAX_TESTS] = - { 0, 0, 0, 1, 1, 1 }; - -static const unsigned char additional[MAX_TESTS][64] = -{ - { 0x00 }, - { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xab, 0xad, 0xda, 0xd2 }, -}; - -static const size_t pt_len[MAX_TESTS] = - { 0, 16, 64, 60, 60, 60 }; - -static const int pt_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 1 }; - -static const unsigned char pt[MAX_TESTS][64] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, - 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, - 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, - 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, - 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, - 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, - 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, - 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, -}; - -static const unsigned char ct[MAX_TESTS * 3][64] = -{ - { 0x00 }, - { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, - 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, - { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, - { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91 }, - { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, - 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, - 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, - 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, - 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, - 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, - 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, - 0xc2, 0x3f, 0x45, 0x98 }, - { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, - 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, - 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, - 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, - 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, - 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, - 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, - 0x4c, 0x34, 0xae, 0xe5 }, - { 0x00 }, - { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, - 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, - { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, - 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, - 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, - 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, - 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, - 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, - 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, - 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, - { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, - 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, - 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, - 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, - 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, - 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, - 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, - 0xcc, 0xda, 0x27, 0x10 }, - { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, - 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, - 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, - 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, - 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, - 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, - 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, - 0xa0, 0xf0, 0x62, 0xf7 }, - { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, - 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, - 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, - 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, - 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, - 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, - 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, - 0xe9, 0xb7, 0x37, 0x3b }, - { 0x00 }, - { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, - 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, - { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, - 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, - 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, - 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, - 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, - 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, - 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, - 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, - { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, - 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, - 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, - 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, - 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, - 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, - 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, - 0xbc, 0xc9, 0xf6, 0x62 }, - { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, - 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, - 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, - 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, - 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, - 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, - 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, - 0xf4, 0x7c, 0x9b, 0x1f }, - { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, - 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, - 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, - 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, - 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, - 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, - 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, - 0x44, 0xae, 0x7e, 0x3f }, -}; - -static const unsigned char tag[MAX_TESTS * 3][16] = -{ - { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, - 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, - { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, - 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, - { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, - 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, - { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, - 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, - { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, - 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, - { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, - 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, - { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, - 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, - { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, - 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, - { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, - 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, - { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, - 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, - { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, - 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, - { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, - 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, - { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, - 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, - { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, - 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, - { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, - 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, - { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, - 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, - { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, - 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, - { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, - 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, -}; - -int mbedtls_gcm_self_test( int verbose ) -{ - mbedtls_gcm_context ctx; - unsigned char buf[64]; - unsigned char tag_buf[16]; - int i, j, ret; - mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; - - mbedtls_gcm_init( &ctx ); - - for( j = 0; j < 3; j++ ) - { - int key_len = 128 + 64 * j; - - for( i = 0; i < MAX_TESTS; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " AES-GCM-%3d #%d (%s): ", - key_len, i, "enc" ); - - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); - - ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, - pt_len[i], - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i], - pt[pt_index[i]], buf, 16, tag_buf ); - - if( ret != 0 || - memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - mbedtls_gcm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " AES-GCM-%3d #%d (%s): ", - key_len, i, "dec" ); - - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); - - ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, - pt_len[i], - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i], - ct[j * 6 + i], buf, 16, tag_buf ); - - if( ret != 0 || - memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - mbedtls_gcm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", - key_len, i, "enc" ); - - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); - - ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i] ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( pt_len[i] > 32 ) - { - size_t rest_len = pt_len[i] - 32; - ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, - buf + 32 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - else - { - ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); - if( ret != 0 || - memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - mbedtls_gcm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", - key_len, i, "dec" ); - - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); - - ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i] ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( pt_len[i] > 32 ) - { - size_t rest_len = pt_len[i] - 32; - ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, - buf + 32 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - else - { - ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); - if( ret != 0 || - memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - mbedtls_gcm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - } - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -#endif /* MBEDTLS_GCM_C */ diff --git a/components/security/mbedtls/src/havege.c b/components/security/mbedtls/src/havege.c deleted file mode 100644 index 2b75ef7b..00000000 --- a/components/security/mbedtls/src/havege.c +++ /dev/null @@ -1,245 +0,0 @@ -/** - * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - * - * 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) - */ -/* - * The HAVEGE RNG was designed by Andre Seznec in 2002. - * - * http://www.irisa.fr/caps/projects/hipsor/publi.php - * - * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_HAVEGE_C) - -#include "mbedtls/havege.h" -#include "mbedtls/timing.h" - -#include - -/* 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; -} - -/* ------------------------------------------------------------------------ - * On average, one iteration accesses two 8-word blocks in the havege WALK - * table, and generates 16 words in the RES array. - * - * The data read in the WALK table is updated and permuted after each use. - * The result of the hardware clock counter read is used for this update. - * - * 25 conditional tests are present. The conditional tests are grouped in - * two nested groups of 12 conditional tests and 1 test that controls the - * permutation; on average, there should be 6 tests executed and 3 of them - * should be mispredicted. - * ------------------------------------------------------------------------ - */ - -#define SWAP(X,Y) { int *T = X; X = Y; Y = T; } - -#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; -#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; - -#define TST1_LEAVE U1++; } -#define TST2_LEAVE U2++; } - -#define ONE_ITERATION \ - \ - PTEST = PT1 >> 20; \ - \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - \ - PTX = (PT1 >> 18) & 7; \ - PT1 &= 0x1FFF; \ - PT2 &= 0x1FFF; \ - CLK = (int) mbedtls_timing_hardclock(); \ - \ - i = 0; \ - A = &WALK[PT1 ]; RES[i++] ^= *A; \ - B = &WALK[PT2 ]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ - \ - IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ - *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ - *B = IN ^ U1; \ - *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ - *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ - B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ - \ - if( PTEST & 1 ) SWAP( A, C ); \ - \ - IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ - *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ - *B = IN; CLK = (int) mbedtls_timing_hardclock(); \ - *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ - *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 4]; \ - B = &WALK[PT2 ^ 1]; \ - \ - PTEST = PT2 >> 1; \ - \ - PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ - PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ - PTY = (PT2 >> 10) & 7; \ - \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - \ - C = &WALK[PT1 ^ 5]; \ - D = &WALK[PT2 ^ 5]; \ - \ - RES[i++] ^= *A; \ - RES[i++] ^= *B; \ - RES[i++] ^= *C; \ - RES[i++] ^= *D; \ - \ - IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ - *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ - *B = IN ^ U2; \ - *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ - *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ - B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ - \ - IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ - *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ - *B = IN; \ - *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ - *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ - \ - PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ - WALK[PT1 ^ PTX ^ 7] ) & (~1); \ - PT1 ^= (PT2 ^ 0x10) & 0x10; \ - \ - for( n++, i = 0; i < 16; i++ ) \ - hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; - -/* - * Entropy gathering function - */ -static void havege_fill( mbedtls_havege_state *hs ) -{ - int i, n = 0; - int U1, U2, *A, *B, *C, *D; - int PT1, PT2, *WALK, RES[16]; - int PTX, PTY, CLK, PTEST, IN; - - WALK = hs->WALK; - PT1 = hs->PT1; - PT2 = hs->PT2; - - PTX = U1 = 0; - PTY = U2 = 0; - - (void)PTX; - - memset( RES, 0, sizeof( RES ) ); - - while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) - { - ONE_ITERATION - ONE_ITERATION - ONE_ITERATION - ONE_ITERATION - } - - hs->PT1 = PT1; - hs->PT2 = PT2; - - hs->offset[0] = 0; - hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; -} - -/* - * HAVEGE initialization - */ -void mbedtls_havege_init( mbedtls_havege_state *hs ) -{ - memset( hs, 0, sizeof( mbedtls_havege_state ) ); - - havege_fill( hs ); -} - -void mbedtls_havege_free( mbedtls_havege_state *hs ) -{ - if( hs == NULL ) - return; - - mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) ); -} - -/* - * HAVEGE rand function - */ -int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) -{ - int val; - size_t use_len; - mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; - unsigned char *p = buf; - - while( len > 0 ) - { - use_len = len; - if( use_len > sizeof(int) ) - use_len = sizeof(int); - - if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) - havege_fill( hs ); - - val = hs->pool[hs->offset[0]++]; - val ^= hs->pool[hs->offset[1]++]; - - memcpy( p, &val, use_len ); - - len -= use_len; - p += use_len; - } - - return( 0 ); -} - -#endif /* MBEDTLS_HAVEGE_C */ diff --git a/components/security/mbedtls/src/hmac_drbg.c b/components/security/mbedtls/src/hmac_drbg.c deleted file mode 100644 index bf5f9b5b..00000000 --- a/components/security/mbedtls/src/hmac_drbg.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * HMAC_DRBG implementation (NIST SP 800-90) - * - * 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) - */ - -/* - * The NIST SP 800-90A DRBGs are described in the following publication. - * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf - * References below are based on rev. 1 (January 2012). - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) - -#include "mbedtls/hmac_drbg.h" - -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_SELF_TEST */ -#endif /* MBEDTLS_PLATFORM_C */ - -/* 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; -} - -/* - * HMAC_DRBG context initialization - */ -void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -/* - * HMAC_DRBG update, using optional additional data (10.1.2.2) - */ -void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) -{ - size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); - unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; - unsigned char sep[1]; - unsigned char K[MBEDTLS_MD_MAX_SIZE]; - - for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) - { - /* Step 1 or 4 */ - mbedtls_md_hmac_reset( &ctx->md_ctx ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); - if( rounds == 2 ) - mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, K ); - - /* Step 2 or 5 */ - mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); - } -} - -/* - * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) - */ -int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, - const mbedtls_md_info_t * md_info, - const unsigned char *data, size_t data_len ) -{ - int ret; - - if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - /* - * Set initial working state. - * Use the V memory location, which is currently all 0, to initialize the - * MD context with an all-zero key. Then set V to its initial value. - */ - mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); - memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); - - mbedtls_hmac_drbg_update( ctx, data, data_len ); - - return( 0 ); -} - -/* - * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) - */ -int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t len ) -{ - unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; - size_t seedlen; - - /* III. Check input length */ - if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || - ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) - { - return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); - } - - memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); - - /* IV. Gather entropy_len bytes of entropy for the seed */ - if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) - return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); - - seedlen = ctx->entropy_len; - - /* 1. Concatenate entropy and additional data if any */ - if( additional != NULL && len != 0 ) - { - memcpy( seed + seedlen, additional, len ); - seedlen += len; - } - - /* 2. Update state */ - mbedtls_hmac_drbg_update( ctx, seed, seedlen ); - - /* 3. Reset reseed_counter */ - ctx->reseed_counter = 1; - - /* 4. Done */ - return( 0 ); -} - -/* - * HMAC_DRBG initialisation (10.1.2.3 + 9.1) - */ -int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, - const mbedtls_md_info_t * md_info, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ) -{ - int ret; - size_t entropy_len, md_size; - - if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - md_size = mbedtls_md_get_size( md_info ); - - /* - * Set initial working state. - * Use the V memory location, which is currently all 0, to initialize the - * MD context with an all-zero key. Then set V to its initial value. - */ - mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); - memset( ctx->V, 0x01, md_size ); - - ctx->f_entropy = f_entropy; - ctx->p_entropy = p_entropy; - - ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; - - /* - * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by - * each hash function, then according to SP800-90A rev1 10.1 table 2, - * min_entropy_len (in bits) is security_strength. - * - * (This also matches the sizes used in the NIST test vectors.) - */ - entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ - md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ - 32; /* better (256+) -> 256 bits */ - - /* - * For initialisation, use more entropy to emulate a nonce - * (Again, matches test vectors.) - */ - ctx->entropy_len = entropy_len * 3 / 2; - - if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) - return( ret ); - - ctx->entropy_len = entropy_len; - - return( 0 ); -} - -/* - * Set prediction resistance - */ -void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, - int resistance ) -{ - ctx->prediction_resistance = resistance; -} - -/* - * Set entropy length grabbed for reseeds - */ -void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) -{ - ctx->entropy_len = len; -} - -/* - * Set reseed interval - */ -void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) -{ - ctx->reseed_interval = interval; -} - -/* - * HMAC_DRBG random function with optional additional data: - * 10.1.2.5 (arabic) + 9.3 (Roman) - */ -int mbedtls_hmac_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t out_len, - const unsigned char *additional, size_t add_len ) -{ - int ret; - mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; - size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); - size_t left = out_len; - unsigned char *out = output; - - /* II. Check request length */ - if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) - return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); - - /* III. Check input length */ - if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) - return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); - - /* 1. (aka VII and IX) Check reseed counter and PR */ - if( ctx->f_entropy != NULL && /* For no-reseeding instances */ - ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || - ctx->reseed_counter > ctx->reseed_interval ) ) - { - if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) - return( ret ); - - add_len = 0; /* VII.4 */ - } - - /* 2. Use additional data if any */ - if( additional != NULL && add_len != 0 ) - mbedtls_hmac_drbg_update( ctx, additional, add_len ); - - /* 3, 4, 5. Generate bytes */ - while( left != 0 ) - { - size_t use_len = left > md_len ? md_len : left; - - mbedtls_md_hmac_reset( &ctx->md_ctx ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); - - memcpy( out, ctx->V, use_len ); - out += use_len; - left -= use_len; - } - - /* 6. Update */ - mbedtls_hmac_drbg_update( ctx, additional, add_len ); - - /* 7. Update reseed counter */ - ctx->reseed_counter++; - - /* 8. Done */ - return( 0 ); -} - -/* - * HMAC_DRBG random function - */ -int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) -{ - int ret; - mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Free an HMAC_DRBG context - */ -void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) -{ - if( ctx == NULL ) - return; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - mbedtls_md_free( &ctx->md_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); -} - -#if defined(MBEDTLS_FS_IO) -int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) -{ - int ret; - FILE *f; - unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "wb" ) ) == NULL ) - return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); - - if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) - goto exit; - - if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) - { - ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; - goto exit; - } - - ret = 0; - -exit: - fclose( f ); - return( ret ); -} - -int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) -{ - FILE *f; - size_t n; - unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) - { - fclose( f ); - return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); - } - - if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); - } - - fclose( f ); - - mbedtls_hmac_drbg_update( ctx, buf, n ); - - return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); -} -#endif /* MBEDTLS_FS_IO */ - - -#if defined(MBEDTLS_SELF_TEST) - -#if !defined(MBEDTLS_SHA1_C) -/* Dummy checkup routine */ -int mbedtls_hmac_drbg_self_test( int verbose ) -{ - (void) verbose; - return( 0 ); -} -#else - -#define OUTPUT_LEN 80 - -/* From a NIST PR=true test vector */ -static const unsigned char entropy_pr[] = { - 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, - 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, - 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, - 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, - 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; -static const unsigned char result_pr[OUTPUT_LEN] = { - 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, - 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, - 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, - 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, - 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, - 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, - 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; - -/* From a NIST PR=false test vector */ -static const unsigned char entropy_nopr[] = { - 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, - 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, - 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, - 0xe9, 0x9d, 0xfe, 0xdf }; -static const unsigned char result_nopr[OUTPUT_LEN] = { - 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, - 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, - 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, - 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, - 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, - 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, - 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; - -/* "Entropy" from buffer */ -static size_t test_offset; -static int hmac_drbg_self_test_entropy( void *data, - unsigned char *buf, size_t len ) -{ - const unsigned char *p = data; - memcpy( buf, p + test_offset, len ); - test_offset += len; - return( 0 ); -} - -#define CHK( c ) if( (c) != 0 ) \ - { \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - return( 1 ); \ - } - -/* - * Checkup routine for HMAC_DRBG with SHA-1 - */ -int mbedtls_hmac_drbg_self_test( int verbose ) -{ - mbedtls_hmac_drbg_context ctx; - unsigned char buf[OUTPUT_LEN]; - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); - - mbedtls_hmac_drbg_init( &ctx ); - - /* - * PR = True - */ - if( verbose != 0 ) - mbedtls_printf( " HMAC_DRBG (PR = True) : " ); - - test_offset = 0; - CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, - hmac_drbg_self_test_entropy, (void *) entropy_pr, - NULL, 0 ) ); - mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); - CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); - CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); - CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); - mbedtls_hmac_drbg_free( &ctx ); - - mbedtls_hmac_drbg_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - /* - * PR = False - */ - if( verbose != 0 ) - mbedtls_printf( " HMAC_DRBG (PR = False) : " ); - - mbedtls_hmac_drbg_init( &ctx ); - - test_offset = 0; - CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, - hmac_drbg_self_test_entropy, (void *) entropy_nopr, - NULL, 0 ) ); - CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); - CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); - CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); - CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); - mbedtls_hmac_drbg_free( &ctx ); - - mbedtls_hmac_drbg_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/components/security/mbedtls/src/mbedtls_alt.c b/components/security/mbedtls/src/mbedtls_alt.c deleted file mode 100644 index def5dc68..00000000 --- a/components/security/mbedtls/src/mbedtls_alt.c +++ /dev/null @@ -1,883 +0,0 @@ -/** - * Copyright (C) 2017 The YunOS IoT Project. All rights reserved. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include -#include - -#include "mbedtls/md.h" - -#if defined(MBEDTLS_DEBUG_C) -#include "mbedtls/debug.h" -#endif - -#if defined(MBEDTLS_THREADING_ALT) -#include "mbedtls/threading.h" -#endif - -#if defined(MBEDTLS_AES_ALT) -#include "mbedtls/aes.h" -#include "mbedtls/cipher.h" -#endif - -#if defined(MBEDTLS_PK_ALT) -#include "mbedtls/rsa.h" -#endif - -#if defined(MBEDTLS_MD5_ALT) -#include "mbedtls/md5.h" -#endif -#if defined(MBEDTLS_SHA1_ALT) -#include "mbedtls/sha1.h" -#endif -#if defined(MBEDTLS_SHA256_ALT) -#include "mbedtls/sha256.h" -#endif - -#if defined(MBEDTLS_PLATFORM_ALT) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc mycalloc -#define mbedtls_free vPortFree -#endif - -#if defined(CONFIG_PLAT_AOS) -#include -#endif - -#if defined(MBEDTLS_AES_ALT) || defined(MBEDTLS_PK_ALT) || defined(MBEDTLS_MD_ALT) -#include "ali_crypto.h" -#endif - -#define MBEDTLS_ALT_PRINT(_f, _a ...) \ - printf("%s %d: "_f, __FUNCTION__, __LINE__, ##_a) - -#define MBEDTLS_ALT_ASSERT(_x) \ - do { \ - if (!(_x)) { \ - printf("ASSERT FAILURE:\n"); \ - printf("%s (%d): %s\n", \ - "file1", __LINE__, __FUNCTION__); \ - while (1) /* loop */; \ - } \ - } while (0) - -#if defined(MBEDTLS_AES_ALT) -/* 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_PLATFORM_ALT) - -#if defined(XTENSE_MALLOC_IRAM) -extern void *iram_heap_malloc(size_t xWantedSize); -extern void iram_heap_free(void *pv); -extern int iram_heap_check_addr(void *addr); - -void * mbedtls_calloc(size_t n, size_t size) -{ - void *buf = NULL; - - if (n == 0 || size == 0) { - return NULL; - } - - buf = iram_heap_malloc(n * size); - if (!buf) { - buf = malloc(n * size); - } - - if (NULL == buf) { - return NULL; - } else { - memset(buf, 0, n * size); - } - - return buf; -} - -void mbedtls_free(void *ptr) -{ - if (NULL == ptr) { - return; - } - - if (iram_heap_check_addr(ptr) == 1) { - iram_heap_free(ptr); - } else { - free(ptr); - } -} - -#else - -void * mbedtls_calloc(size_t n, size_t size) -{ - void *buf = NULL; - -#if defined(CONFIG_PLAT_AOS) - buf = aos_malloc(n * size); -#else - buf = malloc(n * size); -#endif - if (NULL == buf) { - return NULL; - } else { - memset(buf, 0, n * size); - } - - return buf; -} - -void mbedtls_free( void *ptr ) -{ - if (NULL == ptr) { - return; - } - -#if defined(CONFIG_PLAT_AOS) - aos_free(ptr); -#else - free(ptr); -#endif -} - -#endif -#endif - -#if defined(MBEDTLS_THREADING_ALT) -void threading_mutex_init(mbedtls_threading_mutex_t *mutex) -{ - if (mutex == NULL || mutex->is_valid) - return; - - mutex->is_valid = aos_mutex_new(&mutex->mutex) == 0; -} - -void threading_mutex_free(mbedtls_threading_mutex_t *mutex) -{ - if (mutex == NULL || !mutex->is_valid) - return; - - aos_mutex_free(&mutex->mutex); - mutex->is_valid = 0; -} - -int threading_mutex_lock(mbedtls_threading_mutex_t *mutex) -{ - if (mutex == NULL || !mutex->is_valid) - return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); - - if (aos_mutex_lock( &mutex->mutex, AOS_WAIT_FOREVER) != 0 ) - return(MBEDTLS_ERR_THREADING_MUTEX_ERROR); - - return 0; -} - -int threading_mutex_unlock( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL || ! mutex->is_valid ) - return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); - - if( aos_mutex_unlock( &mutex->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - - return( 0 ); -} - -#endif /* MBEDTLS_THREADING_ALT */ - -#if defined(MBEDTLS_AES_ALT) -void mbedtls_aes_init_alt( mbedtls_aes_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_aes_context ) ); -} - -void mbedtls_aes_free_alt( mbedtls_aes_context *ctx ) -{ - if (ctx == NULL) { - return; - } - - if (ctx->ali_ctx) { - mbedtls_free(ctx->ali_ctx); - } - - mbedtls_zeroize(ctx, sizeof(mbedtls_aes_context)); -} - -int mbedtls_aes_setkey_enc_alt( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - if (ctx == NULL || key == NULL || keybits == 0) { - MBEDTLS_ALT_PRINT("invalid input args\n"); - return -1; - } - - if ((keybits >> 3) > 32) { - MBEDTLS_ALT_PRINT("invalid key length - %d\n", keybits >> 3); - return -1; - } else { - ctx->key_len = keybits >> 3; - memcpy(ctx->key, key, ctx->key_len); - } - - return 0; -} - -int mbedtls_aes_setkey_dec_alt( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - if (ctx == NULL || key == NULL || keybits == 0) { - MBEDTLS_ALT_PRINT("invalid input args\n"); - return -1; - } - - if ((keybits >> 3) > 32) { - MBEDTLS_ALT_PRINT("invalid key length - %d\n", keybits >> 3); - return -1; - } else { - ctx->key_len = keybits >> 3; - memcpy(ctx->key, key, ctx->key_len); - } - - return 0; -} - -int mbedtls_aes_crypt_ecb_alt( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - (void)ctx; - (void)mode; - (void)input; - (void)output; - - MBEDTLS_ALT_PRINT("not support!\n"); - - return -1; -} - -int mbedtls_aes_crypt_cbc_alt( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - bool is_enc; - size_t ctx_size; - ali_crypto_result result; - - if (ctx == NULL || - length == 0 || input == NULL || output == NULL) { - MBEDTLS_ALT_PRINT("invalid input args\n"); - return -1; - } - - if (length % 16) { - MBEDTLS_ALT_PRINT("invalid input length - %d\n", (int)length); - return -1; - } - - if (ctx->ali_ctx == NULL) { - result = ali_aes_get_ctx_size(AES_CBC, &ctx_size); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("get ctx size fail - 0x%x\n", result); - return -1; - } - - ctx->ali_ctx = mbedtls_calloc(1, ctx_size); - if (ctx->ali_ctx == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)ctx_size); - return -1; - } else { - memset(ctx->ali_ctx, 0, ctx_size); - } - } - - if (ctx->status == AES_STATUS_INIT) { - if (mode == MBEDTLS_AES_ENCRYPT) { - is_enc = true; - } else { - is_enc = false; - } - - if (ctx->reset) { - result = ali_aes_reset(ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("aes reset fail - 0x%x\n", result); - return -1; - } - } - - result = ali_aes_init(AES_CBC, is_enc, - ctx->key, NULL, ctx->key_len, iv, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("aes init fail - 0x%x\n", result); - return -1; - } else { - ctx->reset = 1; - ctx->status = AES_STATUS_PROCESS; - } - } - - result = ali_aes_process(input, - output, length, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("aes process fail - 0x%x\n", result); - return -1; - } - - return 0; -} - -#endif /* MBEDTLS_AES_ALT */ - -#if defined(MBEDTLS_PK_ALT) -int rsa_verify_alt(void *ctx, size_t hash_id, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - int ret = 0; - bool result1 = false; - ali_crypto_result result; - mbedtls_rsa_context *rsa_ctx; - hash_type_t hash_type; - rsa_padding_t rsa_padding; - size_t pub_key_len; - uint8_t *pub_key = NULL; - - if (ctx == NULL || hash == NULL || sig == NULL) { - MBEDTLS_ALT_PRINT("invalid input args\n"); - return -1; - } - - rsa_ctx = (mbedtls_rsa_context *)ctx; - if (sig_len != rsa_ctx->n_len) { - MBEDTLS_ALT_PRINT("invalid sig len - %d\n", (int)sig_len); - return -1; - } - - if (rsa_ctx->padding != MBEDTLS_RSA_ALT_PKCS_V15) { - MBEDTLS_ALT_PRINT("invalid rsa padding - %d\n", rsa_ctx->padding); - return -1; - } - - switch(hash_id) { - case MBEDTLS_MD_MD5: { - if (hash_len != MD5_HASH_SIZE) { - MBEDTLS_ALT_PRINT("invalid hash len - %d\n", (int)hash_len); - return -1; - } else { - hash_type = MD5; - } - - break; - } - case MBEDTLS_MD_SHA1: { - if (hash_len != SHA1_HASH_SIZE) { - MBEDTLS_ALT_PRINT("invalid hash len - %d\n", (int)hash_len); - return -1; - } else { - hash_type = SHA1; - } - - break; - } - case MBEDTLS_MD_SHA256: { - if (hash_len != SHA256_HASH_SIZE) { - MBEDTLS_ALT_PRINT("invalid hash len - %d\n", (int)hash_len); - return -1; - } else { - hash_type = SHA256; - } - - break; - } - - default: - MBEDTLS_ALT_PRINT("not support hash_id - %d\n", (int)hash_id); - return -1; - } - - result = ali_rsa_get_pubkey_size((size_t)rsa_ctx->n_len, &pub_key_len); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("get pubkey size fail - 0x%x\n", result); - return -1; - } - - pub_key = mbedtls_calloc(1, pub_key_len); - if (pub_key == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)pub_key_len); - ret = -1; - goto _out; - } else { - memset(pub_key, 0, pub_key_len); - } - - result = ali_rsa_init_pubkey(rsa_ctx->n_len << 3, - rsa_ctx->rsa_n, rsa_ctx->n_len, - rsa_ctx->rsa_e, rsa_ctx->e_len, (rsa_pubkey_t *)pub_key); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("init pub_key fail - 0x%x\n", result); - ret = -1; - goto _out; - } - - rsa_padding.type = RSASSA_PKCS1_V1_5; - rsa_padding.pad.rsassa_v1_5.type = hash_type; - result = ali_rsa_verify((rsa_pubkey_t *)pub_key, - hash, hash_len, - sig, sig_len, rsa_padding, &result1); - if (result != ALI_CRYPTO_SUCCESS || result1 == false) { - MBEDTLS_ALT_PRINT("rsa verify fail - 0x%x\n", result); - ret = -1; - goto _out; - } - -_out: - if (pub_key) { - mbedtls_free(pub_key); - } - - return ret; -} - -int rsa_sign_alt(void *ctx, size_t hash_id, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len) -{ - (void)ctx; - (void)hash_id; - - (void)hash; - (void)hash_len; - (void)sig; - (void)sig_len; - - MBEDTLS_ALT_PRINT("not support!\n"); - - return -1; -} - -int rsa_decrypt_alt(void *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen) -{ - (void)ctx; - (void)input; - (void)ilen; - - (void)output; - (void)olen; - - MBEDTLS_ALT_PRINT("not support!\n"); - - return -1; -} - -int rsa_encrypt_alt(void *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen) -{ - int ret = 0; - ali_crypto_result result; - mbedtls_rsa_context *rsa_ctx; - rsa_padding_t rsa_padding; - size_t pub_key_len; - uint8_t *pub_key = NULL; - - if (ctx == NULL || input == NULL || ilen == 0 || - output == NULL || olen == NULL) { - MBEDTLS_ALT_PRINT("invalid input args\n"); - return -1; - } - - rsa_ctx = (mbedtls_rsa_context *)ctx; - if (rsa_ctx->padding != MBEDTLS_RSA_ALT_PKCS_V15) { - MBEDTLS_ALT_PRINT("invalid rsa padding - %d\n", rsa_ctx->padding); - return -1; - } - - result = ali_rsa_get_pubkey_size((size_t)rsa_ctx->n_len, &pub_key_len); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("get pubkey size fail - 0x%x\n", result); - return -1; - } - - pub_key = mbedtls_calloc(1, pub_key_len); - if (pub_key == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)pub_key_len); - ret = -1; - goto _out; - } else { - memset(pub_key, 0, pub_key_len); - } - - result = ali_rsa_init_pubkey(rsa_ctx->n_len << 3, - rsa_ctx->rsa_n, rsa_ctx->n_len, - rsa_ctx->rsa_e, rsa_ctx->e_len, (rsa_pubkey_t *)pub_key); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("init pub_key fail - 0x%x\n", result); - ret = -1; - goto _out; - } - - rsa_padding.type = RSAES_PKCS1_V1_5; - result = ali_rsa_public_encrypt((rsa_pubkey_t *)pub_key, - input, ilen, output, olen, rsa_padding); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("rsa encrypt fail - 0x%x\n", result); - ret = -1; - goto _out; - } - -_out: - if (pub_key) { - mbedtls_free(pub_key); - } - - return ret; -} - -void mbedtls_rsa_init_alt(mbedtls_rsa_context *ctx, - int padding, int hash_id) -{ - memset( ctx, 0, sizeof(mbedtls_rsa_context)); - - ctx->padding = padding; - ctx->hash_id = hash_id; -} - - -void mbedtls_rsa_free_alt(mbedtls_rsa_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_rsa_context)); -} - -#endif /* MBEDTLS_PK_ALT */ - -#if defined(MBEDTLS_MD5_ALT) -void mbedtls_md5_init_alt(mbedtls_md5_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_md5_context)); -} - -void mbedtls_md5_free_alt(mbedtls_md5_context *ctx) -{ - if (ctx == NULL) { - return; - } - - if (ctx->ali_ctx) { - mbedtls_free(ctx->ali_ctx); - } - - mbedtls_zeroize(ctx, sizeof(mbedtls_md5_context)); -} - -void mbedtls_md5_clone_alt(mbedtls_md5_context *dst, - const mbedtls_md5_context *src) -{ - dst->ali_ctx = mbedtls_calloc(1, src->size); - if (dst->ali_ctx == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)src->size); - MBEDTLS_ALT_ASSERT(0); - } - - dst->size = src->size; - memcpy(dst->ali_ctx, src->ali_ctx, dst->size); -} - -void mbedtls_md5_starts_alt(mbedtls_md5_context *ctx) -{ - size_t ctx_size; - hash_type_t type = MD5; - ali_crypto_result result; - - if (NULL == ctx->ali_ctx) { - result = ali_hash_get_ctx_size(type, &ctx_size); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("get ctx size fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - ctx->size = ctx_size; - ctx->ali_ctx = mbedtls_calloc(1, ctx_size); - if (ctx->ali_ctx == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)ctx_size); - MBEDTLS_ALT_ASSERT(0); - } else { - memset(ctx->ali_ctx, 0, ctx_size); - } - } - - result = ali_hash_init(type, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("md5 init fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_md5_update_alt(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen) -{ - ali_crypto_result result; - - result = ali_hash_update(input, ilen, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("md5 update fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_md5_finish_alt(mbedtls_md5_context *ctx, unsigned char output[16]) -{ - ali_crypto_result result; - - result = ali_hash_final(output, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("md5 final fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_md5_alt(const unsigned char *input, size_t ilen, unsigned char output[16]) -{ - mbedtls_md5_context ctx; - - mbedtls_md5_init_alt( &ctx ); - mbedtls_md5_starts_alt( &ctx ); - mbedtls_md5_update_alt( &ctx, input, ilen ); - mbedtls_md5_finish_alt( &ctx, output ); - mbedtls_md5_free_alt( &ctx ); -} -#endif /* MBEDTLS_MD5_ALT */ - -#if defined(MBEDTLS_SHA1_ALT) -void mbedtls_sha1_init_alt(mbedtls_sha1_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_sha1_context)); -} - -void mbedtls_sha1_free_alt(mbedtls_sha1_context *ctx) -{ - if (ctx == NULL) { - return; - } - - if (ctx->ali_ctx) { - mbedtls_free(ctx->ali_ctx); - } - - mbedtls_zeroize(ctx, sizeof(mbedtls_sha1_context)); -} - -void mbedtls_sha1_clone_alt(mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src) -{ - dst->ali_ctx = mbedtls_calloc(1, src->size); - if (dst->ali_ctx == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)src->size); - MBEDTLS_ALT_ASSERT(0); - } - - dst->size = src->size; - memcpy(dst->ali_ctx, src->ali_ctx, dst->size); -} - -void mbedtls_sha1_starts_alt(mbedtls_sha1_context *ctx) -{ - size_t ctx_size; - hash_type_t type = SHA1; - ali_crypto_result result; - - if (NULL == ctx->ali_ctx) { - result = ali_hash_get_ctx_size(type, &ctx_size); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("get ctx size fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - ctx->size = ctx_size; - ctx->ali_ctx = mbedtls_calloc(1, ctx_size); - if (ctx->ali_ctx == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)ctx_size); - MBEDTLS_ALT_ASSERT(0); - } else { - memset(ctx->ali_ctx, 0, ctx_size); - } - } - - result = ali_hash_init(type, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("sha1 init fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_sha1_update_alt(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen) -{ - ali_crypto_result result; - - result = ali_hash_update(input, ilen, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("sha1 update fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_sha1_finish_alt(mbedtls_sha1_context *ctx, unsigned char output[20]) -{ - ali_crypto_result result; - - result = ali_hash_final(output, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("sha1 final fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_sha1_alt(const unsigned char *input, size_t ilen, unsigned char output[20]) -{ - mbedtls_sha1_context ctx; - - mbedtls_sha1_init_alt( &ctx ); - mbedtls_sha1_starts_alt( &ctx ); - mbedtls_sha1_update_alt( &ctx, input, ilen ); - mbedtls_sha1_finish_alt( &ctx, output ); - mbedtls_sha1_free_alt( &ctx ); -} -#endif /* MBEDTLS_SHA1_ALT */ - -#if defined(MBEDTLS_SHA256_ALT) -void mbedtls_sha256_init_alt(mbedtls_sha256_context *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_sha256_context)); -} - -void mbedtls_sha256_free_alt(mbedtls_sha256_context *ctx) -{ - if (ctx == NULL) { - return; - } - - if (ctx->ali_ctx) { - mbedtls_free(ctx->ali_ctx); - } - - mbedtls_zeroize(ctx, sizeof(mbedtls_sha256_context)); -} - -void mbedtls_sha256_clone_alt(mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src) -{ - dst->ali_ctx = mbedtls_calloc(1, src->size); - if (dst->ali_ctx == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)src->size); - MBEDTLS_ALT_ASSERT(0); - } - - dst->size = src->size; - memcpy(dst->ali_ctx, src->ali_ctx, dst->size); -} - -void mbedtls_sha256_starts_alt(mbedtls_sha256_context *ctx, int is224) -{ - size_t ctx_size; - hash_type_t type; - ali_crypto_result result; - - if (is224 == 0) { - type = SHA256; - } else { - type = SHA224; - } - - if (NULL == ctx->ali_ctx) { - result = ali_hash_get_ctx_size(type, &ctx_size); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("get ctx size fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - ctx->size = ctx_size; - ctx->ali_ctx = mbedtls_calloc(1, ctx_size); - if (ctx->ali_ctx == NULL) { - MBEDTLS_ALT_PRINT("mbedtls_calloc(%d) fail\n", (int)ctx_size); - MBEDTLS_ALT_ASSERT(0); - } else { - memset(ctx->ali_ctx, 0, ctx_size); - } - } - - result = ali_hash_init(type, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("sha256 init fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_sha256_update_alt(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen) -{ - ali_crypto_result result; - - result = ali_hash_update(input, ilen, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("sha256 update fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_sha256_finish_alt(mbedtls_sha256_context *ctx, unsigned char output[32]) -{ - ali_crypto_result result; - - result = ali_hash_final(output, ctx->ali_ctx); - if (result != ALI_CRYPTO_SUCCESS) { - MBEDTLS_ALT_PRINT("sha256 final fail - 0x%x\n", result); - MBEDTLS_ALT_ASSERT(0); - } - - return; -} - -void mbedtls_sha256_alt(const unsigned char *input, size_t ilen, unsigned char output[32], int is224) -{ - mbedtls_sha256_context ctx; - - mbedtls_sha256_init_alt( &ctx ); - mbedtls_sha256_starts_alt( &ctx, is224 ); - mbedtls_sha256_update_alt( &ctx, input, ilen ); - mbedtls_sha256_finish_alt( &ctx, output ); - mbedtls_sha256_free_alt( &ctx ); -} -#endif /* MBEDTLS_SHA256_ALT */ - diff --git a/components/security/mbedtls/src/mbedtls_net.c b/components/security/mbedtls/src/mbedtls_net.c deleted file mode 100644 index 7bbb2b35..00000000 --- a/components/security/mbedtls/src/mbedtls_net.c +++ /dev/null @@ -1,427 +0,0 @@ -#include -#include -#include -#include -#include - -#include "mbedtls/config.h" -#include "mbedtls/net_sockets.h" - -#define MBEDTLS_NET_PRINT(_f, ...) \ - printf("%s %d: "_f, __FUNCTION__, __LINE__, ##__VA_ARGS__) - -#if defined(MBEDTLS_NET_ALT) -#if defined(STM32_USE_SPI_WIFI) - -#include "stm32_wifi.h" -#include "mbedtls/net_sockets.h" - -#define WIFI_WRITE_TIMEOUT 200 -#define WIFI_READ_TIMEOUT 200 -#define WIFI_PAYLOAD_SIZE ES_WIFI_PAYLOAD_SIZE -#define WIFI_READ_RETRY_TIME 5 - -void mbedtls_net_init(mbedtls_net_context *ctx) -{ - ctx->fd = -1; -} - -int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto) -{ - WIFI_Status_t ret; - WIFI_Protocol_t type; - uint8_t ip_addr[4]; - - ret = WIFI_GetHostAddress((char *)host, ip_addr); - if (ret != WIFI_STATUS_OK) { - MBEDTLS_NET_PRINT("net_connect: get host addr fail - %d\n", ret); - return MBEDTLS_ERR_NET_UNKNOWN_HOST; - } - - type = proto == MBEDTLS_NET_PROTO_UDP ? - WIFI_UDP_PROTOCOL : WIFI_TCP_PROTOCOL; - ret = WIFI_OpenClientConnection(0, type, "", ip_addr, atoi(port), 0); - if (ret != WIFI_STATUS_OK) { - MBEDTLS_NET_PRINT("net_connect: open client fail - %d\n", ret); - return MBEDTLS_ERR_NET_CONNECT_FAILED; - } - - ctx->fd = 0; - - return ret; -} - -int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len) -{ - WIFI_Status_t ret; - uint16_t send_size; - uint16_t once_len; - uint8_t *pdata = (uint8_t *)buf; - uint16_t send_total = 0; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if (fd < 0) { - MBEDTLS_NET_PRINT("net_send: invalid socket fd\n"); - return MBEDTLS_ERR_NET_INVALID_CONTEXT; - } - - do { - if (len > WIFI_PAYLOAD_SIZE) { - MBEDTLS_NET_PRINT("net_send: buffer length = %d, split data sending\n", len); - once_len = WIFI_PAYLOAD_SIZE; - len -= WIFI_PAYLOAD_SIZE; - } else { - once_len = len; - len = 0; - } - - ret = WIFI_SendData((uint8_t)fd, - pdata, once_len, - &send_size, WIFI_WRITE_TIMEOUT); - if (ret != WIFI_STATUS_OK) { - MBEDTLS_NET_PRINT("net_send: send data fail - %d\n", ret); - return MBEDTLS_ERR_NET_SEND_FAILED; - } - pdata += once_len; - send_total += send_size; - } while (len > 0); - - return send_total; -} - -int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) -{ - WIFI_Status_t ret; - uint16_t recv_size; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if (fd < 0) { - MBEDTLS_NET_PRINT("net_recv: invalid socket fd\n"); - return (MBEDTLS_ERR_NET_INVALID_CONTEXT); - } - - if (len > WIFI_PAYLOAD_SIZE) { - len = WIFI_PAYLOAD_SIZE; - } - int err_count = 0; - do { - ret = WIFI_ReceiveData((uint8_t)fd, - buf, (uint16_t)len, - &recv_size, WIFI_READ_TIMEOUT); - if (ret != WIFI_STATUS_OK) { - MBEDTLS_NET_PRINT("net_recv: receive data fail - %d\n", ret); - return MBEDTLS_ERR_NET_RECV_FAILED; - } - - //TODO, how to identify the connection is shutdown? - if (recv_size == 0) { - if (err_count == WIFI_READ_RETRY_TIME) { - MBEDTLS_NET_PRINT("retry WIFI_ReceiveData %d times failed\n", err_count); - return MBEDTLS_ERR_SSL_WANT_READ; - } else { - err_count++; - MBEDTLS_NET_PRINT("retry WIFI_ReceiveData time %d\n", err_count); - } - } - } while (ret == WIFI_STATUS_OK && recv_size == 0); - - return recv_size; -} - -int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ) -{ - WIFI_Status_t ret; - uint16_t recv_size; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if (fd < 0) { - MBEDTLS_NET_PRINT("net_recv_timeout: invalid socket fd\n"); - return (MBEDTLS_ERR_NET_INVALID_CONTEXT); - } - - if (len > WIFI_PAYLOAD_SIZE) { - len = WIFI_PAYLOAD_SIZE; - } - - // TODO: STM32 WiFi module can't set mqtt default timeout 60000, will return error, need to check with WiFi module, ignore param "timeout" - int err_count = 0; - do { - ret = WIFI_ReceiveData((uint8_t)fd, - buf, (uint16_t)len, - &recv_size, WIFI_READ_TIMEOUT); - if (ret != WIFI_STATUS_OK) { - MBEDTLS_NET_PRINT("net_recv_timeout: receive data fail - %d\n", ret); - return MBEDTLS_ERR_NET_RECV_FAILED; - } - - //TODO, how to identify the connection is shutdown? - if (recv_size == 0) { - if (err_count == WIFI_READ_RETRY_TIME) { - MBEDTLS_NET_PRINT("retry WIFI_ReceiveData %d times failed\n", err_count); - return MBEDTLS_ERR_SSL_WANT_READ; - } else { - err_count++; - MBEDTLS_NET_PRINT("retry WIFI_ReceiveData time %d\n", err_count); - } - } - } while (ret == WIFI_STATUS_OK && recv_size == 0); - - return recv_size; -} - -void mbedtls_net_free(mbedtls_net_context *ctx) -{ - WIFI_Status_t ret; - - if (ctx->fd == -1) { - return; - } - - ret = WIFI_CloseClientConnection((uint32_t)ctx->fd); - if (ret != WIFI_STATUS_OK) { - MBEDTLS_NET_PRINT("net_free: close client fail - %d\n", ret); - return; - } - - ctx->fd = -1; -} - -#else /* STM32_USE_SPI_WIFI */ - -//#include -//#include - -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) -/* -* Check if the requested operation would be blocking on a non-blocking socket -* and thus 'failed' with a negative return value. -*/ -static int net_would_block(const mbedtls_net_context *ctx) -{ - ((void)ctx); - return (WSAGetLastError() == WSAEWOULDBLOCK); -} -#else -static int net_would_block(const mbedtls_net_context *ctx) -{ - /* - * Never return 'WOULD BLOCK' on a non-blocking socket - */ - if ((fcntl(ctx->fd, F_GETFL, 0) & O_NONBLOCK) != O_NONBLOCK) { - return 0; - } - - switch (errno) { -#if defined EAGAIN - case EAGAIN: -#endif -#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: -#endif - return 1; - } - - return 0; -} -#endif - -void mbedtls_net_init(mbedtls_net_context *ctx) -{ - ctx->fd = -1; -} - -int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto) -{ - int ret; - struct addrinfo hints, *addr_list, *cur; - - memset( &hints, 0, sizeof( hints ) ); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; - hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; - - if (getaddrinfo(host, port, &hints, &addr_list) != 0) { - MBEDTLS_NET_PRINT("getaddrinfo fail- errno: %d\n", errno); - return MBEDTLS_ERR_NET_UNKNOWN_HOST; - } - - ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; - - for (cur = addr_list; cur != NULL; cur = cur->ai_next) { - ctx->fd = (int)socket(cur->ai_family, - cur->ai_socktype, cur->ai_protocol); - if (ctx->fd < 0) { - ret = MBEDTLS_ERR_NET_SOCKET_FAILED; - continue; - } - - do { - ret = connect(ctx->fd, cur->ai_addr, cur->ai_addrlen); - if (ret == 0) { - goto _out; - } else { - if (errno == EINTR) { - continue; - } - - break; - } - } while (1); - - close(ctx->fd); - ret = MBEDTLS_ERR_NET_CONNECT_FAILED; - } - -_out: - freeaddrinfo(addr_list); - - return ret; -} - -int mbedtls_net_set_block(mbedtls_net_context *ctx) -{ -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) - u_long n = 0; - return (ioctlsocket(ctx->fd, FIONBIO, &n)); -#else - int flags; - - flags = fcntl(ctx->fd, F_GETFL, 0); - flags &= ~O_NONBLOCK; - - return fcntl(ctx->fd, F_SETFL, flags); -#endif -} - -int mbedtls_net_set_nonblock(mbedtls_net_context *ctx) -{ -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) - u_long n = 1; - return ( ioctlsocket( ctx->fd, FIONBIO, &n ) ); -#else - int flags; - - flags = fcntl(ctx->fd, F_GETFL, 0); - flags |= O_NONBLOCK; - - return fcntl(ctx->fd, F_SETFL, flags); -#endif -} - -int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) -{ - int ret; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if (fd < 0) { - MBEDTLS_NET_PRINT("invalid socket fd\n"); - return (MBEDTLS_ERR_NET_INVALID_CONTEXT); - } - - ret = (int)read(fd, buf, len); - - if (ret < 0) { - if (net_would_block(ctx) != 0) { - return (MBEDTLS_ERR_SSL_WANT_READ); - } - - if (errno == EPIPE || errno == ECONNRESET) { - MBEDTLS_NET_PRINT("net reset - errno: %d\n", errno); - return (MBEDTLS_ERR_NET_CONN_RESET); - } - - if (errno == EINTR) { - return (MBEDTLS_ERR_SSL_WANT_READ); - } - - MBEDTLS_NET_PRINT("net recv failed - errno: %d\n", errno); - return (MBEDTLS_ERR_NET_RECV_FAILED); - } - - return ret; -} - -int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len) -{ - int ret; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if (fd < 0) { - return (MBEDTLS_ERR_NET_INVALID_CONTEXT); - } - - ret = (int)write(fd, buf, len); - - if (ret < 0) { - if (net_would_block(ctx) != 0) { - return (MBEDTLS_ERR_SSL_WANT_WRITE); - } - - if (errno == EPIPE || errno == ECONNRESET) { - MBEDTLS_NET_PRINT("net reset - errno: %d\n", errno); - return (MBEDTLS_ERR_NET_CONN_RESET); - } - - if (errno == EINTR) { - return (MBEDTLS_ERR_SSL_WANT_WRITE); - } - - MBEDTLS_NET_PRINT("net send failed - errno: %d\n", errno); - return (MBEDTLS_ERR_NET_SEND_FAILED); - } - - return ret; -} - -int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ) -{ - int ret; - struct timeval tv; - fd_set read_fds; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if (fd < 0) { - return MBEDTLS_ERR_NET_INVALID_CONTEXT; - } - - FD_ZERO(&read_fds); - FD_SET(fd, &read_fds); - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - - ret = select(fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv); - if (ret == 0) { - return MBEDTLS_ERR_SSL_TIMEOUT; - } - - if (ret < 0) { - if (errno == EINTR) { - return MBEDTLS_ERR_SSL_WANT_READ; - } - - return MBEDTLS_ERR_NET_RECV_FAILED; - } - - return mbedtls_net_recv(ctx, buf, len); -} - -void mbedtls_net_free(mbedtls_net_context *ctx) -{ - if (ctx->fd == -1) { - return; - } - - shutdown(ctx->fd, 2); - close(ctx->fd); - - ctx->fd = -1; -} - -#endif /* STM32_USE_SPI_WIFI */ -#endif /* MBEDTLS_NET_ALT */ diff --git a/components/security/mbedtls/src/mbedtls_ssl.c b/components/security/mbedtls/src/mbedtls_ssl.c deleted file mode 100644 index ad167582..00000000 --- a/components/security/mbedtls/src/mbedtls_ssl.c +++ /dev/null @@ -1,406 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "mbedtls/config.h" -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/x509_crt.h" -#include "mbedtls/net_sockets.h" - -#if defined(MBEDTLS_AES_ALT) -#include "ali_crypto.h" -#endif - -#if defined(MBEDTLS_THREADING_ALT) -#include "mbedtls/threading.h" -#endif - -#define SSL_DEBUG_LEVEL 3 - -#define SSL_PARAM_MAGIC 0x54321212 - -typedef struct _ssl_param_t { - size_t magic; - mbedtls_net_context net; - mbedtls_x509_crt ca_cert; - mbedtls_ssl_config conf; - mbedtls_ssl_context ssl; -} ssl_param_t; - -static int ssl_random(void *prng, unsigned char *output, size_t output_len) -{ - - struct timeval tv; - - (void)prng; - - gettimeofday(&tv, NULL); - -#if defined(MBEDTLS_AES_ALT) - ali_seed((uint8_t *)&tv.tv_usec, sizeof(suseconds_t)); - ali_rand_gen(output, output_len); -#else - extern int rand(); - //srandom((unsigned int)tv.tv_usec); - while(output_len > 0) { - output[output_len - 1] = rand() & 0xFF; - output_len--; - } -#endif - - return 0; -} - -#if defined(MBEDTLS_DEBUG_C) -static void ssl_debug(void *ctx, int level, - const char *file, int line, const char *str) -{ - (void)ctx; - (void) level; - - printf("%s, line: %d: %s", file, line, str); - - return; -} -#endif - -void *mbedtls_ssl_connect(void *tcp_fd, const char *ca_cert, int ca_cert_len) -{ - int ret; - unsigned int result; - ssl_param_t *ssl_param = NULL; - - if (ca_cert == NULL || ca_cert_len <= 0) { - printf("ssl_connect: invalid input args!\n"); - return NULL; - } - - if ((int)tcp_fd < 0) { - printf("ssl_connect: invalid tcp fd - %d\n", (int)tcp_fd); - return NULL; - } - -#if defined(MBEDTLS_DEBUG_C) - mbedtls_debug_set_threshold(SSL_DEBUG_LEVEL); -#endif - -#if defined(MBEDTLS_THREADING_ALT) - mbedtls_threading_set_alt(threading_mutex_init, - threading_mutex_free, - threading_mutex_lock, - threading_mutex_unlock); -#endif - - ssl_param = pvPortMalloc(sizeof(ssl_param_t)); - if (NULL == ssl_param) { - printf("ssl_connect: malloc(%d) fail\n", sizeof(ssl_param_t)); - return NULL; - } else { - memset(ssl_param, 0, sizeof(ssl_param_t)); - - mbedtls_net_init(&ssl_param->net); - mbedtls_x509_crt_init(&ssl_param->ca_cert); - mbedtls_ssl_config_init(&ssl_param->conf); - mbedtls_ssl_init(&ssl_param->ssl); - ssl_param->magic = SSL_PARAM_MAGIC; - } - - /* - * Initialize the connection - */ - ssl_param->net.fd = (int)tcp_fd; - -#if !defined(STM32_USE_SPI_WIFI) - ret = mbedtls_net_set_block(&ssl_param->net); - if (ret != 0) { - printf("ssl_connect: set block failed- 0x%x\n", -ret); - goto _err; - } -#endif - - /* - * Initialize certificates - */ -#if defined(CONFIG_SSL_DEBUG) - printf("...... Loading the CA root certificate ... "); -#endif - - ret = mbedtls_x509_crt_parse(&ssl_param->ca_cert, - (unsigned char *)ca_cert, (size_t)ca_cert_len + 1); - if (ret < 0) { - printf("ssl_connect: x509 parse failed- 0x%x\n", -ret); - goto _err; - } - -#if defined(CONFIG_SSL_DEBUG) - printf("ok (%d skipped)\n", ret); -#endif - - /* - * setup stuff - */ -#if defined(CONFIG_SSL_DEBUG) - printf("...... Setting up the SSL/TLS structure ... "); -#endif - - ret = mbedtls_ssl_config_defaults( - &ssl_param->conf, - MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT); - if (ret != 0) { - printf("ssl_connect: set ssl config failed - %d\n", ret); - goto _err; - } - -#if defined(CONFIG_SSL_DEBUG) - printf("ok\n"); -#endif - - mbedtls_ssl_conf_authmode(&ssl_param->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_ca_chain(&ssl_param->conf, &ssl_param->ca_cert, NULL); - mbedtls_ssl_conf_rng(&ssl_param->conf, ssl_random, NULL); - -#if defined(MBEDTLS_DEBUG_C) - mbedtls_ssl_conf_dbg(&ssl_param->conf, ssl_debug, NULL); -#endif - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - ret = mbedtls_ssl_conf_max_frag_len(&ssl_param->conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096); - if (ret != 0) { - printf("ssl_connect: mbedtls_ssl_conf_max_frag_len returned - %d\n", ret); - goto _err; - } -#endif - - ret = mbedtls_ssl_setup(&ssl_param->ssl, &ssl_param->conf); - if (ret != 0) { - printf("ssl_connect: mbedtls_ssl_setup returned - %d\n", ret); - goto _err; - } - - mbedtls_ssl_set_bio(&ssl_param->ssl, &ssl_param->net, mbedtls_net_send, mbedtls_net_recv, NULL); - - /* - * handshake - */ -#if defined(CONFIG_SSL_DEBUG) - printf("...... Performing the SSL/TLS handshake ... "); -#endif - - while ((ret = mbedtls_ssl_handshake(&ssl_param->ssl)) != 0) { - if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) { - printf("ssl_connect: mbedtls_ssl_handshake returned -0x%x\n", -ret); - goto _err; - } - } - -#if defined(CONFIG_SSL_DEBUG) - printf("ok\n"); -#endif - - /* - * verify the server certificate - */ -#if defined(CONFIG_SSL_DEBUG) - printf("...... Verifying peer X.509 certificate ... "); -#endif - - result = mbedtls_ssl_get_verify_result(&ssl_param->ssl); - if (result != 0) { - printf("ssl_connect: verify result not confirmed - %d\n", result); - goto _err; - } - -#if defined(CONFIG_SSL_DEBUG) - printf("ok\n"); -#endif - - return (void *)ssl_param; - -_err: - if (ssl_param != NULL) { - mbedtls_net_free( &ssl_param->net); - mbedtls_x509_crt_free(&ssl_param->ca_cert); - mbedtls_ssl_free(&ssl_param->ssl); - mbedtls_ssl_config_free(&ssl_param->conf); - - vPortFree(ssl_param); - ssl_param = NULL; - } - - return NULL; -} - -int mbedtls_ssl_send(void *ssl, const char *buffer, int length) -{ - int ret; - int total_len = 0; - int retry = 0; - ssl_param_t *ssl_param; - - if (ssl == NULL || buffer == NULL || length <= 0) { - printf("ssl_send: invalid input args\n"); - return -1; - } - -#if defined(CONFIG_SSL_DEBUG) - printf("...... > Send to server: "); -#endif - - ssl_param = (ssl_param_t *)ssl; - if (ssl_param->magic != SSL_PARAM_MAGIC) { - printf("ssl_send: invalid magic - 0x%x\n", ssl_param->magic); - return -1; - } - - do { - ret = mbedtls_ssl_write(&ssl_param->ssl, - (const unsigned char *)buffer, (size_t)(length - total_len)); - if (ret > 0) { - total_len += ret; - buffer += ret; - } else if (ret == 0) { - /* EOF */ - break; - } else { - if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { - retry ++; - aos_msleep(10); - continue; - } - - if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - /* - * indicate that write already complete, - * if call read again, it will return 0(EOF)) - */ - break; - } - - printf("ssl_send: mbedtls_ssl_write failed - 0x%x\n", -ret); - - return -1; - } - } while (total_len < length && retry < 10); - -#if defined(CONFIG_SSL_DEBUG) - printf("%d bytes sent retry %d\n", ret, retry); -#endif - -#if defined(CONFIG_SSL_DEBUG) - int i = 0; - unsigned char *data = (unsigned char *)buffer; - - printf("send msg(%d %d): \n", length, ret); - for (i = 0; i < ret; i++) { - printf(" %02x ", data[i]); - } - printf("\n"); -#endif - - return ret < 0 ? -1 : total_len; -} - -int mbedtls_ssl_recv(void *ssl, char *buffer, int length) -{ - int ret; - int total_len = 0; - ssl_param_t *ssl_param; - - if (ssl == NULL || buffer == NULL || length <= 0) { - printf("ssl_recv: invalid input args\n"); - return -1; - } else { - ssl_param = (ssl_param_t *)ssl; - if (ssl_param->magic != SSL_PARAM_MAGIC) { - printf("ssl_recv: invalid magic - 0x%x\n", ssl_param->magic); - return -1; - } - } - -#if defined(CONFIG_SSL_DEBUG) - printf("...... < Read from server: "); -#endif - - do { - ret = mbedtls_ssl_read(&ssl_param->ssl, - (unsigned char *)buffer, (size_t)length); - if (ret > 0) { - total_len = ret; - break; - } else if (ret == 0) { - /* EOF */ - return 0; - } else { - if (ret == MBEDTLS_ERR_SSL_WANT_READ) { - return -EAGAIN; - } - - if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - /* - * indicate that read already complete, - * if call read again, it will return 0(EOF)) - */ - break; - } - - printf("ssl_recv: mbedtls_ssl_read failed - 0x%x\n", -ret); - - return -1; - } - } while (0); - -#if defined(CONFIG_SSL_DEBUG) - printf("%d bytes read\n", total_len); -#endif - -#if defined(CONFIG_SSL_DEBUG) - int i = 0; - unsigned char *data = (unsigned char *)buffer; - - printf("recv msg(%d %d): \n", length, total_len); - for (i = 0; i < total_len; i++) { - printf(" %02x ", data[i]); - } - printf("\n"); -#endif - - return total_len; -} - -int mbedtls_ssl_close(void *ssl) -{ - ssl_param_t *ssl_param; - - if (ssl == NULL) { - return 0; - } - - ssl_param = (ssl_param_t *)ssl; - if (ssl_param->magic != SSL_PARAM_MAGIC) { - printf("ssl_close: invalid magic - 0x%x\n", ssl_param->magic); - return -1; - } - - mbedtls_ssl_close_notify(&ssl_param->ssl); - - mbedtls_net_free( &ssl_param->net); - mbedtls_x509_crt_free(&ssl_param->ca_cert); - mbedtls_ssl_free(&ssl_param->ssl); - mbedtls_ssl_config_free(&ssl_param->conf); - - memset(ssl_param, 0, sizeof(ssl_param_t)); - vPortFree(ssl_param); - -#if defined(MBEDTLS_THREADING_ALT) - mbedtls_threading_free_alt(); -#endif - - return 0; -} diff --git a/components/security/mbedtls/src/md.c b/components/security/mbedtls/src/md.c deleted file mode 100644 index 18658652..00000000 --- a/components/security/mbedtls/src/md.c +++ /dev/null @@ -1,473 +0,0 @@ -/** - * \file mbedtls_md.c - * - * \brief Generic message digest wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * 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_MD_C) - -#include "mbedtls/md.h" -#include "mbedtls/md_internal.h" - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -/* 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; -} - -/* - * Reminder: update profiles in x509_crt.c when adding a new hash! - */ -static const int supported_digests[] = { - -#if defined(MBEDTLS_SHA512_C) - MBEDTLS_MD_SHA512, - MBEDTLS_MD_SHA384, -#endif - -#if defined(MBEDTLS_SHA256_C) - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA224, -#endif - -#if defined(MBEDTLS_SHA1_C) - MBEDTLS_MD_SHA1, -#endif - -#if defined(MBEDTLS_RIPEMD160_C) - MBEDTLS_MD_RIPEMD160, -#endif - -#if defined(MBEDTLS_MD5_C) - MBEDTLS_MD_MD5, -#endif - -#if defined(MBEDTLS_MD4_C) - MBEDTLS_MD_MD4, -#endif - -#if defined(MBEDTLS_MD2_C) - MBEDTLS_MD_MD2, -#endif - - MBEDTLS_MD_NONE -}; - -const int *mbedtls_md_list( void ) -{ - return( supported_digests ); -} - -const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) -{ - if( NULL == md_name ) - return( NULL ); - - /* Get the appropriate digest information */ -#if defined(MBEDTLS_MD2_C) - if( !strcmp( "MD2", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); -#endif -#if defined(MBEDTLS_MD4_C) - if( !strcmp( "MD4", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); -#endif -#if defined(MBEDTLS_MD5_C) - if( !strcmp( "MD5", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); -#endif -#if defined(MBEDTLS_RIPEMD160_C) - if( !strcmp( "RIPEMD160", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); -#endif -#if defined(MBEDTLS_SHA1_C) - if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); -#endif -#if defined(MBEDTLS_SHA256_C) - if( !strcmp( "SHA224", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); - if( !strcmp( "SHA256", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); -#endif -#if defined(MBEDTLS_SHA512_C) - if( !strcmp( "SHA384", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); - if( !strcmp( "SHA512", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); -#endif - return( NULL ); -} - -const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) -{ - switch( md_type ) - { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return( &mbedtls_md2_info ); -#endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return( &mbedtls_md4_info ); -#endif -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_MD_MD5: - return( &mbedtls_md5_info ); -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case MBEDTLS_MD_RIPEMD160: - return( &mbedtls_ripemd160_info ); -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_MD_SHA1: - return( &mbedtls_sha1_info ); -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_SHA224: - return( &mbedtls_sha224_info ); - case MBEDTLS_MD_SHA256: - return( &mbedtls_sha256_info ); -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_MD_SHA384: - return( &mbedtls_sha384_info ); - case MBEDTLS_MD_SHA512: - return( &mbedtls_sha512_info ); -#endif - default: - return( NULL ); - } -} - -void mbedtls_md_init( mbedtls_md_context_t *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); -} - -void mbedtls_md_free( mbedtls_md_context_t *ctx ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return; - - if( ctx->md_ctx != NULL ) - ctx->md_info->ctx_free_func( ctx->md_ctx ); - - if( ctx->hmac_ctx != NULL ) - { - mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); - mbedtls_free( ctx->hmac_ctx ); - } - - mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); -} - -int mbedtls_md_clone( mbedtls_md_context_t *dst, - const mbedtls_md_context_t *src ) -{ - if( dst == NULL || dst->md_info == NULL || - src == NULL || src->md_info == NULL || - dst->md_info != src->md_info ) - { - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - } - - dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); - - return( 0 ); -} - -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) -int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) -{ - return mbedtls_md_setup( ctx, md_info, 1 ); -} -#endif - -int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) -{ - if( md_info == NULL || ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) - return( MBEDTLS_ERR_MD_ALLOC_FAILED ); - - if( hmac != 0 ) - { - ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); - if( ctx->hmac_ctx == NULL ) - { - md_info->ctx_free_func( ctx->md_ctx ); - return( MBEDTLS_ERR_MD_ALLOC_FAILED ); - } - } - - ctx->md_info = md_info; - - return( 0 ); -} - -int mbedtls_md_starts( mbedtls_md_context_t *ctx ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->starts_func( ctx->md_ctx ); - - return( 0 ); -} - -int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->update_func( ctx->md_ctx, input, ilen ); - - return( 0 ); -} - -int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->finish_func( ctx->md_ctx, output ); - - return( 0 ); -} - -int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - if( md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - md_info->digest_func( input, ilen, output ); - - return( 0 ); -} - -#if defined(MBEDTLS_FS_IO) -#if 0 -int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) -{ - int ret; - FILE *f; - size_t n; - mbedtls_md_context_t ctx; - unsigned char buf[1024]; - - if( md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); - - mbedtls_md_init( &ctx ); - - if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) - goto cleanup; - - md_info->starts_func( ctx.md_ctx ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - md_info->update_func( ctx.md_ctx, buf, n ); - - if( ferror( f ) != 0 ) - { - ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; - goto cleanup; - } - - md_info->finish_func( ctx.md_ctx, output ); - -cleanup: - fclose( f ); - mbedtls_md_free( &ctx ); - - return( ret ); -} -#endif -#endif /* MBEDTLS_FS_IO */ - -int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) -{ - unsigned char sum[MBEDTLS_MD_MAX_SIZE]; - unsigned char *ipad, *opad; - size_t i; - - if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - if( keylen > (size_t) ctx->md_info->block_size ) - { - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, key, keylen ); - ctx->md_info->finish_func( ctx->md_ctx, sum ); - - keylen = ctx->md_info->size; - key = sum; - } - - ipad = (unsigned char *) ctx->hmac_ctx; - opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; - - memset( ipad, 0x36, ctx->md_info->block_size ); - memset( opad, 0x5C, ctx->md_info->block_size ); - - for( i = 0; i < keylen; i++ ) - { - ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); - opad[i] = (unsigned char)( opad[i] ^ key[i] ); - } - - mbedtls_zeroize( sum, sizeof( sum ) ); - - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); - - return( 0 ); -} - -int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) -{ - if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->update_func( ctx->md_ctx, input, ilen ); - - return( 0 ); -} - -int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) -{ - unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; - unsigned char *opad; - - if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; - - ctx->md_info->finish_func( ctx->md_ctx, tmp ); - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, opad, ctx->md_info->block_size ); - ctx->md_info->update_func( ctx->md_ctx, tmp, ctx->md_info->size ); - ctx->md_info->finish_func( ctx->md_ctx, output ); - - return( 0 ); -} - -int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) -{ - unsigned char *ipad; - - if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ipad = (unsigned char *) ctx->hmac_ctx; - - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); - - return( 0 ); -} - -int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_md_context_t ctx; - int ret; - - if( md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - mbedtls_md_init( &ctx ); - - if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - mbedtls_md_hmac_starts( &ctx, key, keylen ); - mbedtls_md_hmac_update( &ctx, input, ilen ); - mbedtls_md_hmac_finish( &ctx, output ); - - mbedtls_md_free( &ctx ); - - return( 0 ); -} - -int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->process_func( ctx->md_ctx, data ); - - return( 0 ); -} - -unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) -{ - if( md_info == NULL ) - return( 0 ); - - return md_info->size; -} - -mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) -{ - if( md_info == NULL ) - return( MBEDTLS_MD_NONE ); - - return md_info->type; -} - -const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) -{ - if( md_info == NULL ) - return( NULL ); - - return md_info->name; -} - -#endif /* MBEDTLS_MD_C */ diff --git a/components/security/mbedtls/src/md2.c b/components/security/mbedtls/src/md2.c deleted file mode 100644 index 95cbcce6..00000000 --- a/components/security/mbedtls/src/md2.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * RFC 1115/1319 compliant MD2 implementation - * - * 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) - */ -/* - * The MD2 algorithm was designed by Ron Rivest in 1989. - * - * http://www.ietf.org/rfc/rfc1115.txt - * http://www.ietf.org/rfc/rfc1319.txt - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MD2_C) - -#include "mbedtls/md2.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_MD2_ALT) - -/* 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; -} - -static const unsigned char PI_SUBST[256] = -{ - 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, - 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, - 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, - 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, - 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, - 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, - 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, - 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, - 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, - 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, - 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, - 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, - 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, - 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, - 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, - 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, - 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, - 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, - 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, - 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, - 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, - 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, - 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, - 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, - 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, - 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 -}; - -void mbedtls_md2_init( mbedtls_md2_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_md2_context ) ); -} - -void mbedtls_md2_free( mbedtls_md2_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_md2_context ) ); -} - -void mbedtls_md2_clone( mbedtls_md2_context *dst, - const mbedtls_md2_context *src ) -{ - *dst = *src; -} - -/* - * MD2 context setup - */ -void mbedtls_md2_starts( mbedtls_md2_context *ctx ) -{ - memset( ctx->cksum, 0, 16 ); - memset( ctx->state, 0, 46 ); - memset( ctx->buffer, 0, 16 ); - ctx->left = 0; -} - -#if !defined(MBEDTLS_MD2_PROCESS_ALT) -void mbedtls_md2_process( mbedtls_md2_context *ctx ) -{ - int i, j; - unsigned char t = 0; - - for( i = 0; i < 16; i++ ) - { - ctx->state[i + 16] = ctx->buffer[i]; - ctx->state[i + 32] = - (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); - } - - for( i = 0; i < 18; i++ ) - { - for( j = 0; j < 48; j++ ) - { - ctx->state[j] = (unsigned char) - ( ctx->state[j] ^ PI_SUBST[t] ); - t = ctx->state[j]; - } - - t = (unsigned char)( t + i ); - } - - t = ctx->cksum[15]; - - for( i = 0; i < 16; i++ ) - { - ctx->cksum[i] = (unsigned char) - ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); - t = ctx->cksum[i]; - } -} -#endif /* !MBEDTLS_MD2_PROCESS_ALT */ - -/* - * MD2 process buffer - */ -void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - - while( ilen > 0 ) - { - if( ilen > 16 - ctx->left ) - fill = 16 - ctx->left; - else - fill = ilen; - - memcpy( ctx->buffer + ctx->left, input, fill ); - - ctx->left += fill; - input += fill; - ilen -= fill; - - if( ctx->left == 16 ) - { - ctx->left = 0; - mbedtls_md2_process( ctx ); - } - } -} - -/* - * MD2 final digest - */ -void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) -{ - size_t i; - unsigned char x; - - x = (unsigned char)( 16 - ctx->left ); - - for( i = ctx->left; i < 16; i++ ) - ctx->buffer[i] = x; - - mbedtls_md2_process( ctx ); - - memcpy( ctx->buffer, ctx->cksum, 16 ); - mbedtls_md2_process( ctx ); - - memcpy( output, ctx->state, 16 ); -} - -#endif /* !MBEDTLS_MD2_ALT */ - -/* - * output = MD2( input buffer ) - */ -void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - mbedtls_md2_context ctx; - - mbedtls_md2_init( &ctx ); - mbedtls_md2_starts( &ctx ); - mbedtls_md2_update( &ctx, input, ilen ); - mbedtls_md2_finish( &ctx, output ); - mbedtls_md2_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) - -/* - * RFC 1319 test vectors - */ -static const char md2_test_str[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const unsigned char md2_test_sum[7][16] = -{ - { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, - 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, - { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, - 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, - { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, - 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, - { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, - 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, - { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, - 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, - { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, - 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, - { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, - 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } -}; - -/* - * Checkup routine - */ -int mbedtls_md2_self_test( int verbose ) -{ - int i; - unsigned char md2sum[16]; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " MD2 test #%d: ", i + 1 ); - - mbedtls_md2( (unsigned char *) md2_test_str[i], - strlen( md2_test_str[i] ), md2sum ); - - if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MD2_C */ diff --git a/components/security/mbedtls/src/md4.c b/components/security/mbedtls/src/md4.c deleted file mode 100644 index 11a77e3a..00000000 --- a/components/security/mbedtls/src/md4.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * RFC 1186/1320 compliant MD4 implementation - * - * 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) - */ -/* - * The MD4 algorithm was designed by Ron Rivest in 1990. - * - * http://www.ietf.org/rfc/rfc1186.txt - * http://www.ietf.org/rfc/rfc1320.txt - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MD4_C) - -#include "mbedtls/md4.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_MD4_ALT) - -/* 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; -} - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -void mbedtls_md4_init( mbedtls_md4_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_md4_context ) ); -} - -void mbedtls_md4_free( mbedtls_md4_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) ); -} - -void mbedtls_md4_clone( mbedtls_md4_context *dst, - const mbedtls_md4_context *src ) -{ - *dst = *src; -} - -/* - * MD4 context setup - */ -void mbedtls_md4_starts( mbedtls_md4_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -#if !defined(MBEDTLS_MD4_PROCESS_ALT) -void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ) -{ - uint32_t X[16], A, B, C, D; - - GET_UINT32_LE( X[ 0], data, 0 ); - GET_UINT32_LE( X[ 1], data, 4 ); - GET_UINT32_LE( X[ 2], data, 8 ); - GET_UINT32_LE( X[ 3], data, 12 ); - GET_UINT32_LE( X[ 4], data, 16 ); - GET_UINT32_LE( X[ 5], data, 20 ); - GET_UINT32_LE( X[ 6], data, 24 ); - GET_UINT32_LE( X[ 7], data, 28 ); - GET_UINT32_LE( X[ 8], data, 32 ); - GET_UINT32_LE( X[ 9], data, 36 ); - GET_UINT32_LE( X[10], data, 40 ); - GET_UINT32_LE( X[11], data, 44 ); - GET_UINT32_LE( X[12], data, 48 ); - GET_UINT32_LE( X[13], data, 52 ); - GET_UINT32_LE( X[14], data, 56 ); - GET_UINT32_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x, y, z) ((x & y) | ((~x) & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 1], 7 ); - P( C, D, A, B, X[ 2], 11 ); - P( B, C, D, A, X[ 3], 19 ); - P( A, B, C, D, X[ 4], 3 ); - P( D, A, B, C, X[ 5], 7 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[ 7], 19 ); - P( A, B, C, D, X[ 8], 3 ); - P( D, A, B, C, X[ 9], 7 ); - P( C, D, A, B, X[10], 11 ); - P( B, C, D, A, X[11], 19 ); - P( A, B, C, D, X[12], 3 ); - P( D, A, B, C, X[13], 7 ); - P( C, D, A, B, X[14], 11 ); - P( B, C, D, A, X[15], 19 ); - -#undef P -#undef F - -#define F(x,y,z) ((x & y) | (x & z) | (y & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 4], 5 ); - P( C, D, A, B, X[ 8], 9 ); - P( B, C, D, A, X[12], 13 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 5], 5 ); - P( C, D, A, B, X[ 9], 9 ); - P( B, C, D, A, X[13], 13 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[ 6], 5 ); - P( C, D, A, B, X[10], 9 ); - P( B, C, D, A, X[14], 13 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[ 7], 5 ); - P( C, D, A, B, X[11], 9 ); - P( B, C, D, A, X[15], 13 ); - -#undef P -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 8], 9 ); - P( C, D, A, B, X[ 4], 11 ); - P( B, C, D, A, X[12], 15 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[10], 9 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[14], 15 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 9], 9 ); - P( C, D, A, B, X[ 5], 11 ); - P( B, C, D, A, X[13], 15 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[11], 9 ); - P( C, D, A, B, X[ 7], 11 ); - P( B, C, D, A, X[15], 15 ); - -#undef F -#undef P - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} -#endif /* !MBEDTLS_MD4_PROCESS_ALT */ - -/* - * MD4 process buffer - */ -void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, fill ); - mbedtls_md4_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_md4_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, ilen ); - } -} - -static const unsigned char md4_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD4 final digest - */ -void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn ); - mbedtls_md4_update( ctx, msglen, 8 ); - - PUT_UINT32_LE( ctx->state[0], output, 0 ); - PUT_UINT32_LE( ctx->state[1], output, 4 ); - PUT_UINT32_LE( ctx->state[2], output, 8 ); - PUT_UINT32_LE( ctx->state[3], output, 12 ); -} - -#endif /* !MBEDTLS_MD4_ALT */ - -/* - * output = MD4( input buffer ) - */ -void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - mbedtls_md4_context ctx; - - mbedtls_md4_init( &ctx ); - mbedtls_md4_starts( &ctx ); - mbedtls_md4_update( &ctx, input, ilen ); - mbedtls_md4_finish( &ctx, output ); - mbedtls_md4_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) - -/* - * RFC 1320 test vectors - */ -static const char md4_test_str[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const unsigned char md4_test_sum[7][16] = -{ - { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, - 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, - { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, - 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, - { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, - 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, - { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, - 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, - { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, - 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, - { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, - 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, - { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, - 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } -}; - -/* - * Checkup routine - */ -int mbedtls_md4_self_test( int verbose ) -{ - int i; - unsigned char md4sum[16]; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " MD4 test #%d: ", i + 1 ); - - mbedtls_md4( (unsigned char *) md4_test_str[i], - strlen( md4_test_str[i] ), md4sum ); - - if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MD4_C */ diff --git a/components/security/mbedtls/src/md5.c b/components/security/mbedtls/src/md5.c deleted file mode 100644 index 7f68e5c8..00000000 --- a/components/security/mbedtls/src/md5.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * RFC 1321 compliant MD5 implementation - * - * 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) - */ -/* - * The MD5 algorithm was designed by Ron Rivest in 1991. - * - * http://www.ietf.org/rfc/rfc1321.txt - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MD5_C) - -#include "mbedtls/md5.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_MD5_ALT) - -/* 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; -} - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -void mbedtls_md5_init( mbedtls_md5_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_md5_context ) ); -} - -void mbedtls_md5_free( mbedtls_md5_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); -} - -void mbedtls_md5_clone( mbedtls_md5_context *dst, - const mbedtls_md5_context *src ) -{ - *dst = *src; -} - -/* - * MD5 context setup - */ -void mbedtls_md5_starts( mbedtls_md5_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -#if !defined(MBEDTLS_MD5_PROCESS_ALT) -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ) -{ - uint32_t X[16], A, B, C, D; - - GET_UINT32_LE( X[ 0], data, 0 ); - GET_UINT32_LE( X[ 1], data, 4 ); - GET_UINT32_LE( X[ 2], data, 8 ); - GET_UINT32_LE( X[ 3], data, 12 ); - GET_UINT32_LE( X[ 4], data, 16 ); - GET_UINT32_LE( X[ 5], data, 20 ); - GET_UINT32_LE( X[ 6], data, 24 ); - GET_UINT32_LE( X[ 7], data, 28 ); - GET_UINT32_LE( X[ 8], data, 32 ); - GET_UINT32_LE( X[ 9], data, 36 ); - GET_UINT32_LE( X[10], data, 40 ); - GET_UINT32_LE( X[11], data, 44 ); - GET_UINT32_LE( X[12], data, 48 ); - GET_UINT32_LE( X[13], data, 52 ); - GET_UINT32_LE( X[14], data, 56 ); - GET_UINT32_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define P(a,b,c,d,k,s,t) \ -{ \ - a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) - - P( A, B, C, D, 0, 7, 0xD76AA478 ); - P( D, A, B, C, 1, 12, 0xE8C7B756 ); - P( C, D, A, B, 2, 17, 0x242070DB ); - P( B, C, D, A, 3, 22, 0xC1BDCEEE ); - P( A, B, C, D, 4, 7, 0xF57C0FAF ); - P( D, A, B, C, 5, 12, 0x4787C62A ); - P( C, D, A, B, 6, 17, 0xA8304613 ); - P( B, C, D, A, 7, 22, 0xFD469501 ); - P( A, B, C, D, 8, 7, 0x698098D8 ); - P( D, A, B, C, 9, 12, 0x8B44F7AF ); - P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); - P( B, C, D, A, 11, 22, 0x895CD7BE ); - P( A, B, C, D, 12, 7, 0x6B901122 ); - P( D, A, B, C, 13, 12, 0xFD987193 ); - P( C, D, A, B, 14, 17, 0xA679438E ); - P( B, C, D, A, 15, 22, 0x49B40821 ); - -#undef F - -#define F(x,y,z) (y ^ (z & (x ^ y))) - - P( A, B, C, D, 1, 5, 0xF61E2562 ); - P( D, A, B, C, 6, 9, 0xC040B340 ); - P( C, D, A, B, 11, 14, 0x265E5A51 ); - P( B, C, D, A, 0, 20, 0xE9B6C7AA ); - P( A, B, C, D, 5, 5, 0xD62F105D ); - P( D, A, B, C, 10, 9, 0x02441453 ); - P( C, D, A, B, 15, 14, 0xD8A1E681 ); - P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); - P( A, B, C, D, 9, 5, 0x21E1CDE6 ); - P( D, A, B, C, 14, 9, 0xC33707D6 ); - P( C, D, A, B, 3, 14, 0xF4D50D87 ); - P( B, C, D, A, 8, 20, 0x455A14ED ); - P( A, B, C, D, 13, 5, 0xA9E3E905 ); - P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); - P( C, D, A, B, 7, 14, 0x676F02D9 ); - P( B, C, D, A, 12, 20, 0x8D2A4C8A ); - -#undef F - -#define F(x,y,z) (x ^ y ^ z) - - P( A, B, C, D, 5, 4, 0xFFFA3942 ); - P( D, A, B, C, 8, 11, 0x8771F681 ); - P( C, D, A, B, 11, 16, 0x6D9D6122 ); - P( B, C, D, A, 14, 23, 0xFDE5380C ); - P( A, B, C, D, 1, 4, 0xA4BEEA44 ); - P( D, A, B, C, 4, 11, 0x4BDECFA9 ); - P( C, D, A, B, 7, 16, 0xF6BB4B60 ); - P( B, C, D, A, 10, 23, 0xBEBFBC70 ); - P( A, B, C, D, 13, 4, 0x289B7EC6 ); - P( D, A, B, C, 0, 11, 0xEAA127FA ); - P( C, D, A, B, 3, 16, 0xD4EF3085 ); - P( B, C, D, A, 6, 23, 0x04881D05 ); - P( A, B, C, D, 9, 4, 0xD9D4D039 ); - P( D, A, B, C, 12, 11, 0xE6DB99E5 ); - P( C, D, A, B, 15, 16, 0x1FA27CF8 ); - P( B, C, D, A, 2, 23, 0xC4AC5665 ); - -#undef F - -#define F(x,y,z) (y ^ (x | ~z)) - - P( A, B, C, D, 0, 6, 0xF4292244 ); - P( D, A, B, C, 7, 10, 0x432AFF97 ); - P( C, D, A, B, 14, 15, 0xAB9423A7 ); - P( B, C, D, A, 5, 21, 0xFC93A039 ); - P( A, B, C, D, 12, 6, 0x655B59C3 ); - P( D, A, B, C, 3, 10, 0x8F0CCC92 ); - P( C, D, A, B, 10, 15, 0xFFEFF47D ); - P( B, C, D, A, 1, 21, 0x85845DD1 ); - P( A, B, C, D, 8, 6, 0x6FA87E4F ); - P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); - P( C, D, A, B, 6, 15, 0xA3014314 ); - P( B, C, D, A, 13, 21, 0x4E0811A1 ); - P( A, B, C, D, 4, 6, 0xF7537E82 ); - P( D, A, B, C, 11, 10, 0xBD3AF235 ); - P( C, D, A, B, 2, 15, 0x2AD7D2BB ); - P( B, C, D, A, 9, 21, 0xEB86D391 ); - -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} -#endif /* !MBEDTLS_MD5_PROCESS_ALT */ - -/* - * MD5 process buffer - */ -void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_md5_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_md5_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), input, ilen ); - } -} - -static const unsigned char md5_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD5 final digest - */ -void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_md5_update( ctx, md5_padding, padn ); - mbedtls_md5_update( ctx, msglen, 8 ); - - PUT_UINT32_LE( ctx->state[0], output, 0 ); - PUT_UINT32_LE( ctx->state[1], output, 4 ); - PUT_UINT32_LE( ctx->state[2], output, 8 ); - PUT_UINT32_LE( ctx->state[3], output, 12 ); -} - -/* - * output = MD5( input buffer ) - */ -void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - mbedtls_md5_context ctx; - - mbedtls_md5_init( &ctx ); - mbedtls_md5_starts( &ctx ); - mbedtls_md5_update( &ctx, input, ilen ); - mbedtls_md5_finish( &ctx, output ); - mbedtls_md5_free( &ctx ); -} - -#endif /* !MBEDTLS_MD5_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * RFC 1321 test vectors - */ -static const unsigned char md5_test_buf[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const int md5_test_buflen[7] = -{ - 0, 1, 3, 14, 26, 62, 80 -}; - -static const unsigned char md5_test_sum[7][16] = -{ - { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, - 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, - { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, - 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, - { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, - 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, - { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, - 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, - { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, - 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, - { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, - 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, - { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, - 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } -}; - -/* - * Checkup routine - */ -int mbedtls_md5_self_test( int verbose ) -{ - int i; - unsigned char md5sum[16]; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " MD5 test #%d: ", i + 1 ); - - mbedtls_md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); - - if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MD5_C */ diff --git a/components/security/mbedtls/src/md_wrap.c b/components/security/mbedtls/src/md_wrap.c deleted file mode 100644 index 9d561e21..00000000 --- a/components/security/mbedtls/src/md_wrap.c +++ /dev/null @@ -1,749 +0,0 @@ -/** - * \file md_wrap.c - * - * \brief Generic message digest wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * 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_MD_C) - -#include "mbedtls/md_internal.h" - -#if defined(MBEDTLS_MD2_C) -#include "mbedtls/md2.h" -#endif - -#if defined(MBEDTLS_MD4_C) -#include "mbedtls/md4.h" -#endif - -#if defined(MBEDTLS_MD5_C) -#include "mbedtls/md5.h" -#endif - -#if defined(MBEDTLS_RIPEMD160_C) -#include "mbedtls/ripemd160.h" -#endif - -#if defined(MBEDTLS_SHA1_C) -#include "mbedtls/sha1.h" -#endif - -#if defined(MBEDTLS_SHA256_C) -#include "mbedtls/sha256.h" -#endif - -#if defined(MBEDTLS_SHA512_C) -#include "mbedtls/sha512.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_MD2_C) - -static void md2_starts_wrap( void *ctx ) -{ - mbedtls_md2_starts( (mbedtls_md2_context *) ctx ); -} - -static void md2_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_md2_update( (mbedtls_md2_context *) ctx, input, ilen ); -} - -static void md2_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_md2_finish( (mbedtls_md2_context *) ctx, output ); -} - -static void *md2_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); - - if( ctx != NULL ) - mbedtls_md2_init( (mbedtls_md2_context *) ctx ); - - return( ctx ); -} - -static void md2_ctx_free( void *ctx ) -{ - mbedtls_md2_free( (mbedtls_md2_context *) ctx ); - mbedtls_free( ctx ); -} - -static void md2_clone_wrap( void *dst, const void *src ) -{ - mbedtls_md2_clone( (mbedtls_md2_context *) dst, - (const mbedtls_md2_context *) src ); -} - -static void md2_process_wrap( void *ctx, const unsigned char *data ) -{ - ((void) data); - - mbedtls_md2_process( (mbedtls_md2_context *) ctx ); -} - -const mbedtls_md_info_t mbedtls_md2_info = { - MBEDTLS_MD_MD2, - "MD2", - 16, - 16, - md2_starts_wrap, - md2_update_wrap, - md2_finish_wrap, - mbedtls_md2, - md2_ctx_alloc, - md2_ctx_free, - md2_clone_wrap, - md2_process_wrap, -}; - -#endif /* MBEDTLS_MD2_C */ - -#if defined(MBEDTLS_MD4_C) - -static void md4_starts_wrap( void *ctx ) -{ - mbedtls_md4_starts( (mbedtls_md4_context *) ctx ); -} - -static void md4_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_md4_update( (mbedtls_md4_context *) ctx, input, ilen ); -} - -static void md4_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_md4_finish( (mbedtls_md4_context *) ctx, output ); -} - -static void *md4_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); - - if( ctx != NULL ) - mbedtls_md4_init( (mbedtls_md4_context *) ctx ); - - return( ctx ); -} - -static void md4_ctx_free( void *ctx ) -{ - mbedtls_md4_free( (mbedtls_md4_context *) ctx ); - mbedtls_free( ctx ); -} - -static void md4_clone_wrap( void *dst, const void *src ) -{ - mbedtls_md4_clone( (mbedtls_md4_context *) dst, - (const mbedtls_md4_context *) src ); -} - -static void md4_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_md4_process( (mbedtls_md4_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_md4_info = { - MBEDTLS_MD_MD4, - "MD4", - 16, - 64, - md4_starts_wrap, - md4_update_wrap, - md4_finish_wrap, - mbedtls_md4, - md4_ctx_alloc, - md4_ctx_free, - md4_clone_wrap, - md4_process_wrap, -}; - -#endif /* MBEDTLS_MD4_C */ - -#if defined(MBEDTLS_MD5_C) - -#if !defined(MBEDTLS_MD5_ALT) -static void md5_starts_wrap( void *ctx ) -{ - mbedtls_md5_starts( (mbedtls_md5_context *) ctx ); -} - -static void md5_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_md5_update( (mbedtls_md5_context *) ctx, input, ilen ); -} - -static void md5_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_md5_finish( (mbedtls_md5_context *) ctx, output ); -} - -static void *md5_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); - - if( ctx != NULL ) - mbedtls_md5_init( (mbedtls_md5_context *) ctx ); - - return( ctx ); -} - -static void md5_ctx_free( void *ctx ) -{ - mbedtls_md5_free( (mbedtls_md5_context *) ctx ); - mbedtls_free( ctx ); -} - -static void md5_clone_wrap( void *dst, const void *src ) -{ - mbedtls_md5_clone( (mbedtls_md5_context *) dst, - (const mbedtls_md5_context *) src ); -} - -static void md5_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_md5_process( (mbedtls_md5_context *) ctx, data ); -} - -#else /* !MBEDTLS_MD5_ALT */ - -static void md5_starts_wrap( void *ctx ) -{ - mbedtls_md5_starts_alt( (mbedtls_md5_context *) ctx ); -} - -static void md5_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_md5_update_alt( (mbedtls_md5_context *) ctx, input, ilen ); -} - -static void md5_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_md5_finish_alt( (mbedtls_md5_context *) ctx, output ); -} - -static void *md5_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); - - if( ctx != NULL ) - mbedtls_md5_init_alt( (mbedtls_md5_context *) ctx ); - - return( ctx ); -} - -static void md5_ctx_free( void *ctx ) -{ - mbedtls_md5_free_alt( (mbedtls_md5_context *) ctx ); - mbedtls_free( ctx ); -} - -static void md5_clone_wrap( void *dst, const void *src ) -{ - mbedtls_md5_clone_alt( (mbedtls_md5_context *) dst, - (const mbedtls_md5_context *) src ); -} - -static void md5_process_wrap( void *ctx, const unsigned char *data ) -{ - (void)ctx; - (void)data; -} - -#endif /* !MBEDTLS_MD5_ALT */ - -const mbedtls_md_info_t mbedtls_md5_info = { - MBEDTLS_MD_MD5, - "MD5", - 16, - 64, - md5_starts_wrap, - md5_update_wrap, - md5_finish_wrap, -#if !defined(MBEDTLS_MD5_ALT) - mbedtls_md5, -#else - mbedtls_md5_alt, -#endif - md5_ctx_alloc, - md5_ctx_free, - md5_clone_wrap, - md5_process_wrap, -}; - -#endif /* MBEDTLS_MD5_C */ - -#if defined(MBEDTLS_RIPEMD160_C) - -static void ripemd160_starts_wrap( void *ctx ) -{ - mbedtls_ripemd160_starts( (mbedtls_ripemd160_context *) ctx ); -} - -static void ripemd160_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_ripemd160_update( (mbedtls_ripemd160_context *) ctx, input, ilen ); -} - -static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_ripemd160_finish( (mbedtls_ripemd160_context *) ctx, output ); -} - -static void *ripemd160_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); - - if( ctx != NULL ) - mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); - - return( ctx ); -} - -static void ripemd160_ctx_free( void *ctx ) -{ - mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); - mbedtls_free( ctx ); -} - -static void ripemd160_clone_wrap( void *dst, const void *src ) -{ - mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, - (const mbedtls_ripemd160_context *) src ); -} - -static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_ripemd160_process( (mbedtls_ripemd160_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_ripemd160_info = { - MBEDTLS_MD_RIPEMD160, - "RIPEMD160", - 20, - 64, - ripemd160_starts_wrap, - ripemd160_update_wrap, - ripemd160_finish_wrap, - mbedtls_ripemd160, - ripemd160_ctx_alloc, - ripemd160_ctx_free, - ripemd160_clone_wrap, - ripemd160_process_wrap, -}; - -#endif /* MBEDTLS_RIPEMD160_C */ - -#if defined(MBEDTLS_SHA1_C) - -#if !defined(MBEDTLS_SHA1_ALT) -static void sha1_starts_wrap( void *ctx ) -{ - mbedtls_sha1_starts( (mbedtls_sha1_context *) ctx ); -} - -static void sha1_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_sha1_update( (mbedtls_sha1_context *) ctx, input, ilen ); -} - -static void sha1_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_sha1_finish( (mbedtls_sha1_context *) ctx, output ); -} - -static void *sha1_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); - - if( ctx != NULL ) - mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); - - return( ctx ); -} - -static void sha1_clone_wrap( void *dst, const void *src ) -{ - mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, - (const mbedtls_sha1_context *) src ); -} - -static void sha1_ctx_free( void *ctx ) -{ - mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); - mbedtls_free( ctx ); -} - -static void sha1_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_sha1_process( (mbedtls_sha1_context *) ctx, data ); -} - -#else /* MBEDTLS_SHA1_ALT */ -static void sha1_starts_wrap( void *ctx ) -{ - mbedtls_sha1_starts_alt( (mbedtls_sha1_context *) ctx ); -} - -static void sha1_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_sha1_update_alt( (mbedtls_sha1_context *) ctx, input, ilen ); -} - -static void sha1_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_sha1_finish_alt( (mbedtls_sha1_context *) ctx, output ); -} - -static void *sha1_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); - - if( ctx != NULL ) - mbedtls_sha1_init_alt( (mbedtls_sha1_context *) ctx ); - - return( ctx ); -} - -static void sha1_clone_wrap( void *dst, const void *src ) -{ - mbedtls_sha1_clone_alt( (mbedtls_sha1_context *) dst, - (const mbedtls_sha1_context *) src ); -} - -static void sha1_ctx_free( void *ctx ) -{ - mbedtls_sha1_free_alt( (mbedtls_sha1_context *) ctx ); - mbedtls_free( ctx ); -} - -static void sha1_process_wrap( void *ctx, const unsigned char *data ) -{ - (void)ctx; - (void)data; -} - -#endif /* MBEDTLS_SHA1_ALT */ - -const mbedtls_md_info_t mbedtls_sha1_info = { - MBEDTLS_MD_SHA1, - "SHA1", - 20, - 64, - sha1_starts_wrap, - sha1_update_wrap, - sha1_finish_wrap, -#if !defined(MBEDTLS_SHA1_ALT) - mbedtls_sha1, -#else - mbedtls_sha1_alt, -#endif - sha1_ctx_alloc, - sha1_ctx_free, - sha1_clone_wrap, - sha1_process_wrap, -}; - -#endif /* MBEDTLS_SHA1_C */ - -/* - * Wrappers for generic message digests - */ -#if defined(MBEDTLS_SHA256_C) - -#if !defined(MBEDTLS_SHA256_ALT) -static void sha224_starts_wrap( void *ctx ) -{ - mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 1 ); -} - -static void sha224_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_sha256_update( (mbedtls_sha256_context *) ctx, input, ilen ); -} - -static void sha224_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); -} - -static void sha224_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha256( input, ilen, output, 1 ); -} - -static void *sha224_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); - - if( ctx != NULL ) - mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); - - return( ctx ); -} - -static void sha224_ctx_free( void *ctx ) -{ - mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); - mbedtls_free( ctx ); -} - -static void sha224_clone_wrap( void *dst, const void *src ) -{ - mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, - (const mbedtls_sha256_context *) src ); -} - -static void sha224_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_sha256_process( (mbedtls_sha256_context *) ctx, data ); -} - -#else /* MBEDTLS_SHA256_ALT */ - -static void sha224_starts_wrap( void *ctx ) -{ - mbedtls_sha256_starts_alt( (mbedtls_sha256_context *) ctx, 1 ); -} - -static void sha224_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_sha256_update_alt( (mbedtls_sha256_context *) ctx, input, ilen ); -} - -static void sha224_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_sha256_finish_alt( (mbedtls_sha256_context *) ctx, output ); -} - -static void sha224_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha256_alt( input, ilen, output, 1 ); -} - -static void *sha224_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); - - if( ctx != NULL ) - mbedtls_sha256_init_alt( (mbedtls_sha256_context *) ctx ); - - return( ctx ); -} - -static void sha224_ctx_free( void *ctx ) -{ - mbedtls_sha256_free_alt( (mbedtls_sha256_context *) ctx ); - mbedtls_free( ctx ); -} - -static void sha224_clone_wrap( void *dst, const void *src ) -{ - mbedtls_sha256_clone_alt( (mbedtls_sha256_context *) dst, - (const mbedtls_sha256_context *) src ); -} - -static void sha224_process_wrap( void *ctx, const unsigned char *data ) -{ - (void)ctx; - (void)data; -} -#endif /* MBEDTLS_SHA256_ALT */ - -const mbedtls_md_info_t mbedtls_sha224_info = { - MBEDTLS_MD_SHA224, - "SHA224", - 28, - 64, - sha224_starts_wrap, - sha224_update_wrap, - sha224_finish_wrap, - sha224_wrap, - sha224_ctx_alloc, - sha224_ctx_free, - sha224_clone_wrap, - sha224_process_wrap, -}; - -#if !defined(MBEDTLS_SHA256_ALT) -static void sha256_starts_wrap( void *ctx ) -{ - mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 0 ); -} - -static void sha256_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha256( input, ilen, output, 0 ); -} - -#else /* MBEDTLS_SHA256_ALT */ - -static void sha256_starts_wrap( void *ctx ) -{ - mbedtls_sha256_starts_alt( (mbedtls_sha256_context *) ctx, 0 ); -} - -static void sha256_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha256_alt( input, ilen, output, 0 ); -} -#endif /* MBEDTLS_SHA256_ALT */ - -const mbedtls_md_info_t mbedtls_sha256_info = { - MBEDTLS_MD_SHA256, - "SHA256", - 32, - 64, - sha256_starts_wrap, - sha224_update_wrap, - sha224_finish_wrap, - sha256_wrap, - sha224_ctx_alloc, - sha224_ctx_free, - sha224_clone_wrap, - sha224_process_wrap, -}; - -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - -static void sha384_starts_wrap( void *ctx ) -{ - mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 1 ); -} - -static void sha384_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_sha512_update( (mbedtls_sha512_context *) ctx, input, ilen ); -} - -static void sha384_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_sha512_finish( (mbedtls_sha512_context *) ctx, output ); -} - -static void sha384_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha512( input, ilen, output, 1 ); -} - -static void *sha384_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); - - if( ctx != NULL ) - mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); - - return( ctx ); -} - -static void sha384_ctx_free( void *ctx ) -{ - mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); - mbedtls_free( ctx ); -} - -static void sha384_clone_wrap( void *dst, const void *src ) -{ - mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, - (const mbedtls_sha512_context *) src ); -} - -static void sha384_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_sha512_process( (mbedtls_sha512_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_sha384_info = { - MBEDTLS_MD_SHA384, - "SHA384", - 48, - 128, - sha384_starts_wrap, - sha384_update_wrap, - sha384_finish_wrap, - sha384_wrap, - sha384_ctx_alloc, - sha384_ctx_free, - sha384_clone_wrap, - sha384_process_wrap, -}; - -static void sha512_starts_wrap( void *ctx ) -{ - mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 0 ); -} - -static void sha512_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha512( input, ilen, output, 0 ); -} - -const mbedtls_md_info_t mbedtls_sha512_info = { - MBEDTLS_MD_SHA512, - "SHA512", - 64, - 128, - sha512_starts_wrap, - sha384_update_wrap, - sha384_finish_wrap, - sha512_wrap, - sha384_ctx_alloc, - sha384_ctx_free, - sha384_clone_wrap, - sha384_process_wrap, -}; - -#endif /* MBEDTLS_SHA512_C */ - -#endif /* MBEDTLS_MD_C */ diff --git a/components/security/mbedtls/src/memory_buffer_alloc.c b/components/security/mbedtls/src/memory_buffer_alloc.c deleted file mode 100644 index 545d5a2c..00000000 --- a/components/security/mbedtls/src/memory_buffer_alloc.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - * Buffer-based memory allocator - * - * 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_MEMORY_BUFFER_ALLOC_C) -#include "mbedtls/memory_buffer_alloc.h" - -/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C - is dependent upon MBEDTLS_PLATFORM_C */ -#include "mbedtls/platform.h" - -#include - -#if defined(MBEDTLS_MEMORY_BACKTRACE) -#include -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -/* 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; -} - -#define MAGIC1 0xFF00AA55 -#define MAGIC2 0xEE119966 -#define MAX_BT 20 - -typedef struct _memory_header memory_header; -struct _memory_header -{ - size_t magic1; - size_t size; - size_t alloc; - memory_header *prev; - memory_header *next; - memory_header *prev_free; - memory_header *next_free; -#if defined(MBEDTLS_MEMORY_BACKTRACE) - char **trace; - size_t trace_count; -#endif - size_t magic2; -}; - -typedef struct -{ - unsigned char *buf; - size_t len; - memory_header *first; - memory_header *first_free; - int verify; -#if defined(MBEDTLS_MEMORY_DEBUG) - size_t alloc_count; - size_t free_count; - size_t total_used; - size_t maximum_used; - size_t header_count; - size_t maximum_header_count; -#endif -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} -buffer_alloc_ctx; - -static buffer_alloc_ctx heap; - -#if defined(MBEDTLS_MEMORY_DEBUG) -static void debug_header( memory_header *hdr ) -{ -#if defined(MBEDTLS_MEMORY_BACKTRACE) - size_t i; -#endif - - mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " - "ALLOC(%zu), SIZE(%10zu)\n", - (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, - hdr->alloc, hdr->size ); - mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", - (size_t) hdr->prev_free, (size_t) hdr->next_free ); - -#if defined(MBEDTLS_MEMORY_BACKTRACE) - mbedtls_fprintf( stderr, "TRACE: \n" ); - for( i = 0; i < hdr->trace_count; i++ ) - mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); - mbedtls_fprintf( stderr, "\n" ); -#endif -} - -static void debug_chain() -{ - memory_header *cur = heap.first; - - mbedtls_fprintf( stderr, "\nBlock list\n" ); - while( cur != NULL ) - { - debug_header( cur ); - cur = cur->next; - } - - mbedtls_fprintf( stderr, "Free list\n" ); - cur = heap.first_free; - - while( cur != NULL ) - { - debug_header( cur ); - cur = cur->next_free; - } -} -#endif /* MBEDTLS_MEMORY_DEBUG */ - -static int verify_header( memory_header *hdr ) -{ - if( hdr->magic1 != MAGIC1 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); -#endif - return( 1 ); - } - - if( hdr->magic2 != MAGIC2 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); -#endif - return( 1 ); - } - - if( hdr->alloc > 1 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); -#endif - return( 1 ); - } - - if( hdr->prev != NULL && hdr->prev == hdr->next ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); -#endif - return( 1 ); - } - - if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); -#endif - return( 1 ); - } - - return( 0 ); -} - -static int verify_chain() -{ - memory_header *prv = heap.first, *cur = heap.first->next; - - if( verify_header( heap.first ) != 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: verification of first header " - "failed\n" ); -#endif - return( 1 ); - } - - if( heap.first->prev != NULL ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: verification failed: " - "first->prev != NULL\n" ); -#endif - return( 1 ); - } - - while( cur != NULL ) - { - if( verify_header( cur ) != 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: verification of header " - "failed\n" ); -#endif - return( 1 ); - } - - if( cur->prev != prv ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: verification failed: " - "cur->prev != prv\n" ); -#endif - return( 1 ); - } - - prv = cur; - cur = cur->next; - } - - return( 0 ); -} - -static void *buffer_alloc_calloc( size_t n, size_t size ) -{ - memory_header *new, *cur = heap.first_free; - unsigned char *p; - void *ret; - size_t original_len, len; -#if defined(MBEDTLS_MEMORY_BACKTRACE) - void *trace_buffer[MAX_BT]; - size_t trace_cnt; -#endif - - if( heap.buf == NULL || heap.first == NULL ) - return( NULL ); - - original_len = len = n * size; - - if( n != 0 && len / n != size ) - return( NULL ); - - if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) - { - len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; - len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; - } - - // Find block that fits - // - while( cur != NULL ) - { - if( cur->size >= len ) - break; - - cur = cur->next_free; - } - - if( cur == NULL ) - return( NULL ); - - if( cur->alloc != 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " - "data\n" ); -#endif - mbedtls_exit( 1 ); - } - -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.alloc_count++; -#endif - - // Found location, split block if > memory_header + 4 room left - // - if( cur->size - len < sizeof(memory_header) + - MBEDTLS_MEMORY_ALIGN_MULTIPLE ) - { - cur->alloc = 1; - - // Remove from free_list - // - if( cur->prev_free != NULL ) - cur->prev_free->next_free = cur->next_free; - else - heap.first_free = cur->next_free; - - if( cur->next_free != NULL ) - cur->next_free->prev_free = cur->prev_free; - - cur->prev_free = NULL; - cur->next_free = NULL; - -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.total_used += cur->size; - if( heap.total_used > heap.maximum_used ) - heap.maximum_used = heap.total_used; -#endif -#if defined(MBEDTLS_MEMORY_BACKTRACE) - trace_cnt = backtrace( trace_buffer, MAX_BT ); - cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); - cur->trace_count = trace_cnt; -#endif - - if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) - mbedtls_exit( 1 ); - - ret = (unsigned char *) cur + sizeof( memory_header ); - memset( ret, 0, original_len ); - - return( ret ); - } - - p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; - new = (memory_header *) p; - - new->size = cur->size - len - sizeof(memory_header); - new->alloc = 0; - new->prev = cur; - new->next = cur->next; -#if defined(MBEDTLS_MEMORY_BACKTRACE) - new->trace = NULL; - new->trace_count = 0; -#endif - new->magic1 = MAGIC1; - new->magic2 = MAGIC2; - - if( new->next != NULL ) - new->next->prev = new; - - // Replace cur with new in free_list - // - new->prev_free = cur->prev_free; - new->next_free = cur->next_free; - if( new->prev_free != NULL ) - new->prev_free->next_free = new; - else - heap.first_free = new; - - if( new->next_free != NULL ) - new->next_free->prev_free = new; - - cur->alloc = 1; - cur->size = len; - cur->next = new; - cur->prev_free = NULL; - cur->next_free = NULL; - -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.header_count++; - if( heap.header_count > heap.maximum_header_count ) - heap.maximum_header_count = heap.header_count; - heap.total_used += cur->size; - if( heap.total_used > heap.maximum_used ) - heap.maximum_used = heap.total_used; -#endif -#if defined(MBEDTLS_MEMORY_BACKTRACE) - trace_cnt = backtrace( trace_buffer, MAX_BT ); - cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); - cur->trace_count = trace_cnt; -#endif - - if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) - mbedtls_exit( 1 ); - - ret = (unsigned char *) cur + sizeof( memory_header ); - memset( ret, 0, original_len ); - - return( ret ); -} - -static void buffer_alloc_free( void *ptr ) -{ - memory_header *hdr, *old = NULL; - unsigned char *p = (unsigned char *) ptr; - - if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) - return; - - if( p < heap.buf || p > heap.buf + heap.len ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " - "space\n" ); -#endif - mbedtls_exit( 1 ); - } - - p -= sizeof(memory_header); - hdr = (memory_header *) p; - - if( verify_header( hdr ) != 0 ) - mbedtls_exit( 1 ); - - if( hdr->alloc != 1 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " - "data\n" ); -#endif - mbedtls_exit( 1 ); - } - - hdr->alloc = 0; - -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.free_count++; - heap.total_used -= hdr->size; -#endif - -#if defined(MBEDTLS_MEMORY_BACKTRACE) - free( hdr->trace ); - hdr->trace = NULL; - hdr->trace_count = 0; -#endif - - // Regroup with block before - // - if( hdr->prev != NULL && hdr->prev->alloc == 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.header_count--; -#endif - hdr->prev->size += sizeof(memory_header) + hdr->size; - hdr->prev->next = hdr->next; - old = hdr; - hdr = hdr->prev; - - if( hdr->next != NULL ) - hdr->next->prev = hdr; - - memset( old, 0, sizeof(memory_header) ); - } - - // Regroup with block after - // - if( hdr->next != NULL && hdr->next->alloc == 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.header_count--; -#endif - hdr->size += sizeof(memory_header) + hdr->next->size; - old = hdr->next; - hdr->next = hdr->next->next; - - if( hdr->prev_free != NULL || hdr->next_free != NULL ) - { - if( hdr->prev_free != NULL ) - hdr->prev_free->next_free = hdr->next_free; - else - heap.first_free = hdr->next_free; - - if( hdr->next_free != NULL ) - hdr->next_free->prev_free = hdr->prev_free; - } - - hdr->prev_free = old->prev_free; - hdr->next_free = old->next_free; - - if( hdr->prev_free != NULL ) - hdr->prev_free->next_free = hdr; - else - heap.first_free = hdr; - - if( hdr->next_free != NULL ) - hdr->next_free->prev_free = hdr; - - if( hdr->next != NULL ) - hdr->next->prev = hdr; - - memset( old, 0, sizeof(memory_header) ); - } - - // Prepend to free_list if we have not merged - // (Does not have to stay in same order as prev / next list) - // - if( old == NULL ) - { - hdr->next_free = heap.first_free; - if( heap.first_free != NULL ) - heap.first_free->prev_free = hdr; - heap.first_free = hdr; - } - - if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) - mbedtls_exit( 1 ); -} - -void mbedtls_memory_buffer_set_verify( int verify ) -{ - heap.verify = verify; -} - -int mbedtls_memory_buffer_alloc_verify() -{ - return verify_chain(); -} - -#if defined(MBEDTLS_MEMORY_DEBUG) -void mbedtls_memory_buffer_alloc_status() -{ - mbedtls_fprintf( stderr, - "Current use: %zu blocks / %zu bytes, max: %zu blocks / " - "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", - heap.header_count, heap.total_used, - heap.maximum_header_count, heap.maximum_used, - heap.maximum_header_count * sizeof( memory_header ) - + heap.maximum_used, - heap.alloc_count, heap.free_count ); - - if( heap.first->next == NULL ) - mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); - else - { - mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); - debug_chain(); - } -} - -void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) -{ - *max_used = heap.maximum_used; - *max_blocks = heap.maximum_header_count; -} - -void mbedtls_memory_buffer_alloc_max_reset( void ) -{ - heap.maximum_used = 0; - heap.maximum_header_count = 0; -} - -void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) -{ - *cur_used = heap.total_used; - *cur_blocks = heap.header_count; -} -#endif /* MBEDTLS_MEMORY_DEBUG */ - -#if defined(MBEDTLS_THREADING_C) -static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) -{ - void *buf; - if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) - return( NULL ); - buf = buffer_alloc_calloc( n, size ); - if( mbedtls_mutex_unlock( &heap.mutex ) ) - return( NULL ); - return( buf ); -} - -static void buffer_alloc_free_mutexed( void *ptr ) -{ - /* We have to good option here, but corrupting the heap seems - * worse than loosing memory. */ - if( mbedtls_mutex_lock( &heap.mutex ) ) - return; - buffer_alloc_free( ptr ); - (void) mbedtls_mutex_unlock( &heap.mutex ); -} -#endif /* MBEDTLS_THREADING_C */ - -void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) -{ - memset( &heap, 0, sizeof(buffer_alloc_ctx) ); - memset( buf, 0, len ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &heap.mutex ); - mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, - buffer_alloc_free_mutexed ); -#else - mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); -#endif - - if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) - { - /* Adjust len first since buf is used in the computation */ - len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE - - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; - buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE - - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; - } - - heap.buf = buf; - heap.len = len; - - heap.first = (memory_header *) buf; - heap.first->size = len - sizeof(memory_header); - heap.first->magic1 = MAGIC1; - heap.first->magic2 = MAGIC2; - heap.first_free = heap.first; -} - -void mbedtls_memory_buffer_alloc_free() -{ -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &heap.mutex ); -#endif - mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) ); -} - -#if defined(MBEDTLS_SELF_TEST) -static int check_pointer( void *p ) -{ - if( p == NULL ) - return( -1 ); - - if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) - return( -1 ); - - return( 0 ); -} - -static int check_all_free( ) -{ - if( -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.total_used != 0 || -#endif - heap.first != heap.first_free || - (void *) heap.first != (void *) heap.buf ) - { - return( -1 ); - } - - return( 0 ); -} - -#define TEST_ASSERT( condition ) \ - if( ! (condition) ) \ - { \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - \ - ret = 1; \ - goto cleanup; \ - } - -int mbedtls_memory_buffer_alloc_self_test( int verbose ) -{ - unsigned char buf[1024]; - unsigned char *p, *q, *r, *end; - int ret = 0; - - if( verbose != 0 ) - mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); - - mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); - - p = mbedtls_calloc( 1, 1 ); - q = mbedtls_calloc( 1, 128 ); - r = mbedtls_calloc( 1, 16 ); - - TEST_ASSERT( check_pointer( p ) == 0 && - check_pointer( q ) == 0 && - check_pointer( r ) == 0 ); - - mbedtls_free( r ); - mbedtls_free( q ); - mbedtls_free( p ); - - TEST_ASSERT( check_all_free( ) == 0 ); - - /* Memorize end to compare with the next test */ - end = heap.buf + heap.len; - - mbedtls_memory_buffer_alloc_free( ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " MBA test #2 (buf not aligned): " ); - - mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); - - TEST_ASSERT( heap.buf + heap.len == end ); - - p = mbedtls_calloc( 1, 1 ); - q = mbedtls_calloc( 1, 128 ); - r = mbedtls_calloc( 1, 16 ); - - TEST_ASSERT( check_pointer( p ) == 0 && - check_pointer( q ) == 0 && - check_pointer( r ) == 0 ); - - mbedtls_free( r ); - mbedtls_free( q ); - mbedtls_free( p ); - - TEST_ASSERT( check_all_free( ) == 0 ); - - mbedtls_memory_buffer_alloc_free( ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " MBA test #3 (full): " ); - - mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); - - p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); - - TEST_ASSERT( check_pointer( p ) == 0 ); - TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); - - mbedtls_free( p ); - - p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); - q = mbedtls_calloc( 1, 16 ); - - TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); - TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); - - mbedtls_free( q ); - - TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); - - mbedtls_free( p ); - - TEST_ASSERT( check_all_free( ) == 0 ); - - mbedtls_memory_buffer_alloc_free( ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - mbedtls_memory_buffer_alloc_free( ); - - return( ret ); -} -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ diff --git a/components/security/mbedtls/src/mycalloc.c b/components/security/mbedtls/src/mycalloc.c deleted file mode 100644 index 92a6adba..00000000 --- a/components/security/mbedtls/src/mycalloc.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -void *mycalloc(size_t numitems, size_t size) -{ - size_t sizel = numitems * size; - void *ptr = pvPortMalloc(sizel); - memset(ptr, 0, sizel); - return ptr; -} diff --git a/components/security/mbedtls/src/net_sockets.c b/components/security/mbedtls/src/net_sockets.c deleted file mode 100644 index 076f1960..00000000 --- a/components/security/mbedtls/src/net_sockets.c +++ /dev/null @@ -1,593 +0,0 @@ -/* - * TCP/IP or UDP/IP networking 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_NET_ALT) - -#if defined(MBEDTLS_NET_C) - -#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) -#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#endif - -#include "mbedtls/net_sockets.h" - -#include - -#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ - !defined(EFI32) - -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -/* Enables getaddrinfo() & Co */ -#define _WIN32_WINNT 0x0501 -#include - -#include -#include - -#if defined(_MSC_VER) -#if defined(_WIN32_WCE) -#pragma comment( lib, "ws2.lib" ) -#else -#pragma comment( lib, "ws2_32.lib" ) -#endif -#endif /* _MSC_VER */ - -#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0) -#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0) -#define close(fd) closesocket(fd) - -static int wsa_init_done = 0; - -#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ - -/* Some MS functions want int and MSVC warns if we pass size_t, - * but the standard fucntions use socklen_t, so cast only for MSVC */ -#if defined(_MSC_VER) -#define MSVC_INT_CAST (int) -#else -#define MSVC_INT_CAST -#endif - -#include - -#include - -#include - -/* - * Prepare for using the sockets interface - */ -static int net_prepare( void ) -{ -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) - WSADATA wsaData; - - if( wsa_init_done == 0 ) - { - if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) - return( MBEDTLS_ERR_NET_SOCKET_FAILED ); - - wsa_init_done = 1; - } -#else -#if !defined(EFIX64) && !defined(EFI32) - signal( SIGPIPE, SIG_IGN ); -#endif -#endif - return( 0 ); -} - -/* - * Initialize a context - */ -void mbedtls_net_init( mbedtls_net_context *ctx ) -{ - ctx->fd = -1; -} - -/* - * Initiate a TCP connection with host:port and the given protocol - */ -int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, - const char *port, int proto ) -{ - int ret; - struct addrinfo hints, *addr_list, *cur; - - if( ( ret = net_prepare() ) != 0 ) - return( ret ); - - /* Do name resolution with both IPv6 and IPv4 */ - memset( &hints, 0, sizeof( hints ) ); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; - hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; - - if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) - return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); - - /* Try the sockaddrs until a connection succeeds */ - ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; - for( cur = addr_list; cur != NULL; cur = cur->ai_next ) - { - ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, - cur->ai_protocol ); - if( ctx->fd < 0 ) - { - ret = MBEDTLS_ERR_NET_SOCKET_FAILED; - continue; - } - - if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) - { - ret = 0; - break; - } - - close( ctx->fd ); - ret = MBEDTLS_ERR_NET_CONNECT_FAILED; - } - - freeaddrinfo( addr_list ); - - return( ret ); -} - -/* - * Create a listening socket on bind_ip:port - */ -int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) -{ - int n, ret; - struct addrinfo hints, *addr_list, *cur; - - if( ( ret = net_prepare() ) != 0 ) - return( ret ); - - /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ - memset( &hints, 0, sizeof( hints ) ); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; - hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; - if( bind_ip == NULL ) - hints.ai_flags = AI_PASSIVE; - - if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) - return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); - - /* Try the sockaddrs until a binding succeeds */ - ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; - for( cur = addr_list; cur != NULL; cur = cur->ai_next ) - { - ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, - cur->ai_protocol ); - if( ctx->fd < 0 ) - { - ret = MBEDTLS_ERR_NET_SOCKET_FAILED; - continue; - } - - n = 1; - if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, - (const char *) &n, sizeof( n ) ) != 0 ) - { - close( ctx->fd ); - ret = MBEDTLS_ERR_NET_SOCKET_FAILED; - continue; - } - - if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) - { - close( ctx->fd ); - ret = MBEDTLS_ERR_NET_BIND_FAILED; - continue; - } - - /* Listen only makes sense for TCP */ - if( proto == MBEDTLS_NET_PROTO_TCP ) - { - if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) - { - close( ctx->fd ); - ret = MBEDTLS_ERR_NET_LISTEN_FAILED; - continue; - } - } - - /* Bind was successful */ - ret = 0; - break; - } - - freeaddrinfo( addr_list ); - - return( ret ); - -} - -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) -/* - * Check if the requested operation would be blocking on a non-blocking socket - * and thus 'failed' with a negative return value. - */ -static int net_would_block( const mbedtls_net_context *ctx ) -{ - ((void) ctx); - return( WSAGetLastError() == WSAEWOULDBLOCK ); -} -#else -/* - * Check if the requested operation would be blocking on a non-blocking socket - * and thus 'failed' with a negative return value. - * - * Note: on a blocking socket this function always returns 0! - */ -static int net_would_block( const mbedtls_net_context *ctx ) -{ - /* - * Never return 'WOULD BLOCK' on a non-blocking socket - */ - if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) - return( 0 ); - - switch( errno ) - { -#if defined EAGAIN - case EAGAIN: -#endif -#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: -#endif - return( 1 ); - } - return( 0 ); -} -#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ - -/* - * Accept a connection from a remote client - */ -int mbedtls_net_accept( mbedtls_net_context *bind_ctx, - mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len ) -{ - int ret; - int type; - - struct sockaddr_storage client_addr; - -#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ - defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) - socklen_t n = (socklen_t) sizeof( client_addr ); - socklen_t type_len = (socklen_t) sizeof( type ); -#else - int n = (int) sizeof( client_addr ); - int type_len = (int) sizeof( type ); -#endif - - /* Is this a TCP or UDP socket? */ - if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, - (void *) &type, &type_len ) != 0 || - ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) - { - return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); - } - - if( type == SOCK_STREAM ) - { - /* TCP: actual accept() */ - ret = client_ctx->fd = (int) accept( bind_ctx->fd, - (struct sockaddr *) &client_addr, &n ); - } - else - { - /* UDP: wait for a message, but keep it in the queue */ - char buf[1] = { 0 }; - - ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, - (struct sockaddr *) &client_addr, &n ); - -#if defined(_WIN32) - if( ret == SOCKET_ERROR && - WSAGetLastError() == WSAEMSGSIZE ) - { - /* We know buf is too small, thanks, just peeking here */ - ret = 0; - } -#endif - } - - if( ret < 0 ) - { - if( net_would_block( bind_ctx ) != 0 ) - return( MBEDTLS_ERR_SSL_WANT_READ ); - - return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); - } - - /* UDP: hijack the listening socket to communicate with the client, - * then bind a new socket to accept new connections */ - if( type != SOCK_STREAM ) - { - struct sockaddr_storage local_addr; - int one = 1; - - if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) - return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); - - client_ctx->fd = bind_ctx->fd; - bind_ctx->fd = -1; /* In case we exit early */ - - n = sizeof( struct sockaddr_storage ); - if( getsockname( client_ctx->fd, - (struct sockaddr *) &local_addr, &n ) != 0 || - ( bind_ctx->fd = (int) socket( local_addr.ss_family, - SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || - setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, - (const char *) &one, sizeof( one ) ) != 0 ) - { - return( MBEDTLS_ERR_NET_SOCKET_FAILED ); - } - - if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) - { - return( MBEDTLS_ERR_NET_BIND_FAILED ); - } - } - - if( client_ip != NULL ) - { - if( client_addr.ss_family == AF_INET ) - { - struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; - *ip_len = sizeof( addr4->sin_addr.s_addr ); - - if( buf_size < *ip_len ) - return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); - - memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); - } - else - { - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; - *ip_len = sizeof( addr6->sin6_addr.s6_addr ); - - if( buf_size < *ip_len ) - return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); - - memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); - } - } - - return( 0 ); -} - -/* - * Set the socket blocking or non-blocking - */ -int mbedtls_net_set_block( mbedtls_net_context *ctx ) -{ -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) - u_long n = 0; - return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); -#else - return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); -#endif -} - -int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) -{ -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) - u_long n = 1; - return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); -#else - return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); -#endif -} - -/* - * Portable usleep helper - */ -void mbedtls_net_usleep( unsigned long usec ) -{ -#if defined(_WIN32) - Sleep( ( usec + 999 ) / 1000 ); -#else - struct timeval tv; - tv.tv_sec = usec / 1000000; -#if defined(__unix__) || defined(__unix) || \ - ( defined(__APPLE__) && defined(__MACH__) ) - tv.tv_usec = (suseconds_t) usec % 1000000; -#else - tv.tv_usec = usec % 1000000; -#endif - select( 0, NULL, NULL, NULL, &tv ); -#endif -} - -/* - * Read at most 'len' characters - */ -int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) -{ - int ret; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if( fd < 0 ) - return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); - - errno = 0; - ret = (int) read( fd, buf, len ); - - if( ret < 0 ) - { - if( net_would_block( ctx ) != 0 ) - return( MBEDTLS_ERR_SSL_WANT_READ ); - -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) - if( WSAGetLastError() == WSAECONNRESET ) - return( MBEDTLS_ERR_NET_CONN_RESET ); -#else - if( errno == EPIPE || errno == ECONNRESET ) - return( MBEDTLS_ERR_NET_CONN_RESET ); - - if( errno == EINTR ) - return( MBEDTLS_ERR_SSL_WANT_READ ); -#endif - - printf("net recv failed - errno: %d\n", errno); - return( MBEDTLS_ERR_NET_RECV_FAILED ); - } - - return( ret ); -} - -/* - * Read at most 'len' characters, blocking for at most 'timeout' ms - */ -int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ) -{ - int ret; - struct timeval tv; - fd_set read_fds; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if( fd < 0 ) - return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); - - FD_ZERO( &read_fds ); - FD_SET( fd, &read_fds ); - - tv.tv_sec = timeout / 1000; - tv.tv_usec = ( timeout % 1000 ) * 1000; - - ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); - - /* Zero fds ready means we timed out */ - if( ret == 0 ) - return( MBEDTLS_ERR_SSL_TIMEOUT ); - - if( ret < 0 ) - { -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) - if( WSAGetLastError() == WSAEINTR ) - return( MBEDTLS_ERR_SSL_WANT_READ ); -#else - if( errno == EINTR ) - return( MBEDTLS_ERR_SSL_WANT_READ ); -#endif - - return( MBEDTLS_ERR_NET_RECV_FAILED ); - } - - /* This call will not block */ - return( mbedtls_net_recv( ctx, buf, len ) ); -} - -/* - * Write at most 'len' characters - */ -int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) -{ - int ret; - int fd = ((mbedtls_net_context *) ctx)->fd; - - if( fd < 0 ) - return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); - - errno = 0; - ret = (int) write( fd, buf, len ); - - if( ret < 0 ) - { - if( net_would_block( ctx ) != 0 ) - return( MBEDTLS_ERR_SSL_WANT_WRITE ); - -#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ - !defined(EFI32) - if( WSAGetLastError() == WSAECONNRESET ) - return( MBEDTLS_ERR_NET_CONN_RESET ); -#else - if( errno == EPIPE || errno == ECONNRESET ) - return( MBEDTLS_ERR_NET_CONN_RESET ); - - if( errno == EINTR ) - return( MBEDTLS_ERR_SSL_WANT_WRITE ); -#endif - - return( MBEDTLS_ERR_NET_SEND_FAILED ); - } - - return( ret ); -} - -/* - * Gracefully close the connection - */ -void mbedtls_net_free( mbedtls_net_context *ctx ) -{ - if( ctx->fd == -1 ) - return; - - shutdown( ctx->fd, 2 ); - close( ctx->fd ); - - ctx->fd = -1; -} - -#endif /* MBEDTLS_NET_C */ - -#endif /* MBEDTLS_NET_ALT */ diff --git a/components/security/mbedtls/src/oid.c b/components/security/mbedtls/src/oid.c deleted file mode 100644 index f13826ed..00000000 --- a/components/security/mbedtls/src/oid.c +++ /dev/null @@ -1,710 +0,0 @@ -/** - * \file oid.c - * - * \brief Object Identifier (OID) database - * - * 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_OID_C) - -#include "mbedtls/oid.h" -#include "mbedtls/rsa.h" - -#include -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_snprintf snprintf -#endif - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -#include "mbedtls/x509.h" -#endif - -/* - * Macro to automatically add the size of #define'd OIDs - */ -#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) - -/* - * Macro to generate an internal function for oid_XXX_from_asn1() (used by - * the other functions) - */ -#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ -static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedtls_asn1_buf *oid ) \ -{ \ - const TYPE_T *p = LIST; \ - const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *) p; \ - if( p == NULL || oid == NULL ) return( NULL ); \ - while( cur->asn1 != NULL ) { \ - if( cur->asn1_len == oid->len && \ - memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ - return( p ); \ - } \ - p++; \ - cur = (const mbedtls_oid_descriptor_t *) p; \ - } \ - return( NULL ); \ -} - -/* - * Macro to generate a function for retrieving a single attribute from the - * descriptor of an mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ -int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ -{ \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ - if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ - *ATTR1 = data->descriptor.ATTR1; \ - return( 0 ); \ -} - -/* - * Macro to generate a function for retrieving a single attribute from an - * mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ -int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ -{ \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ - if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ - *ATTR1 = data->ATTR1; \ - return( 0 ); \ -} - -/* - * Macro to generate a function for retrieving two attributes from an - * mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ - ATTR2_TYPE, ATTR2) \ -int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ -{ \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ - if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ - *ATTR1 = data->ATTR1; \ - *ATTR2 = data->ATTR2; \ - return( 0 ); \ -} - -/* - * Macro to generate a function for retrieving the OID based on a single - * attribute from a mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ -int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ -{ \ - const TYPE_T *cur = LIST; \ - while( cur->descriptor.asn1 != NULL ) { \ - if( cur->ATTR1 == ATTR1 ) { \ - *oid = cur->descriptor.asn1; \ - *olen = cur->descriptor.asn1_len; \ - return( 0 ); \ - } \ - cur++; \ - } \ - return( MBEDTLS_ERR_OID_NOT_FOUND ); \ -} - -/* - * Macro to generate a function for retrieving the OID based on two - * attributes from a mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ - ATTR2_TYPE, ATTR2) \ -int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ - size_t *olen ) \ -{ \ - const TYPE_T *cur = LIST; \ - while( cur->descriptor.asn1 != NULL ) { \ - if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ - *oid = cur->descriptor.asn1; \ - *olen = cur->descriptor.asn1_len; \ - return( 0 ); \ - } \ - cur++; \ - } \ - return( MBEDTLS_ERR_OID_NOT_FOUND ); \ -} - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -/* - * For X520 attribute types - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - const char *short_name; -} oid_x520_attr_t; - -static const oid_x520_attr_t oid_x520_attr_type[] = -{ - { - { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, - "CN", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, - "C", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, - "L", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, - "ST", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, - "O", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, - "OU", - }, - { - { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, - "emailAddress", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, - "serialNumber", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, - "postalAddress", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, - "postalCode", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, - "SN", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, - "GN", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, - "initials", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, - "generationQualifier", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, - "title", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, - "dnQualifier", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, - "pseudonym", - }, - { - { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, - "DC", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, - "uniqueIdentifier", - }, - { - { NULL, 0, NULL, NULL }, - NULL, - } -}; - -FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) -FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) - -/* - * For X509 extensions - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - int ext_type; -} oid_x509_ext_t; - -static const oid_x509_ext_t oid_x509_ext[] = -{ - { - { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, - MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, - }, - { - { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, - MBEDTLS_X509_EXT_KEY_USAGE, - }, - { - { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, - MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, - }, - { - { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, - MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, - }, - { - { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, - MBEDTLS_X509_EXT_NS_CERT_TYPE, - }, - { - { NULL, 0, NULL, NULL }, - 0, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) -FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) - -static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = -{ - { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, - { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, - { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, - { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, - { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, - { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, - { NULL, 0, NULL, NULL }, -}; - -FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) -FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) -#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ - -#if defined(MBEDTLS_MD_C) -/* - * For SignatureAlgorithmIdentifier - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; - mbedtls_pk_type_t pk_alg; -} oid_sig_alg_t; - -static const oid_sig_alg_t oid_sig_alg[] = -{ -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_MD2_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, - MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, - MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, - MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, - MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, - MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, - }, - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, - MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, - MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, - }, - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, - MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_SHA1_C) - { - { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, - MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECDSA_C) -#if defined(MBEDTLS_SHA1_C) - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, - MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, - MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, - }, - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, - MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, - MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, - }, - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, - MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_ECDSA_C */ -#if defined(MBEDTLS_RSA_C) - { - { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, - MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, - }, -#endif /* MBEDTLS_RSA_C */ - { - { NULL, 0, NULL, NULL }, - MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) -FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) -FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) -FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) -#endif /* MBEDTLS_MD_C */ - -/* - * For PublicKeyInfo (PKCS1, RFC 5480) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_pk_type_t pk_alg; -} oid_pk_alg_t; - -static const oid_pk_alg_t oid_pk_alg[] = -{ - { - { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, - MBEDTLS_PK_RSA, - }, - { - { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, - MBEDTLS_PK_ECKEY, - }, - { - { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, - MBEDTLS_PK_ECKEY_DH, - }, - { - { NULL, 0, NULL, NULL }, - MBEDTLS_PK_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) - -#if defined(MBEDTLS_ECP_C) -/* - * For namedCurve (RFC 5480) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_ecp_group_id grp_id; -} oid_ecp_grp_t; - -static const oid_ecp_grp_t oid_ecp_grp[] = -{ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, - MBEDTLS_ECP_DP_SECP192R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, - MBEDTLS_ECP_DP_SECP224R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, - MBEDTLS_ECP_DP_SECP256R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, - MBEDTLS_ECP_DP_SECP384R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, - MBEDTLS_ECP_DP_SECP521R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, - MBEDTLS_ECP_DP_SECP192K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, - MBEDTLS_ECP_DP_SECP224K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, - MBEDTLS_ECP_DP_SECP256K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, - MBEDTLS_ECP_DP_BP256R1, - }, -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, - MBEDTLS_ECP_DP_BP384R1, - }, -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, - MBEDTLS_ECP_DP_BP512R1, - }, -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - { - { NULL, 0, NULL, NULL }, - MBEDTLS_ECP_DP_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) -FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_CIPHER_C) -/* - * For PKCS#5 PBES2 encryption algorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_cipher_type_t cipher_alg; -} oid_cipher_alg_t; - -static const oid_cipher_alg_t oid_cipher_alg[] = -{ - { - { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, - MBEDTLS_CIPHER_DES_CBC, - }, - { - { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, - MBEDTLS_CIPHER_DES_EDE3_CBC, - }, - { - { NULL, 0, NULL, NULL }, - MBEDTLS_CIPHER_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_MD_C) -/* - * For digestAlgorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; -} oid_md_alg_t; - -static const oid_md_alg_t oid_md_alg[] = -{ -#if defined(MBEDTLS_MD2_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, - MBEDTLS_MD_MD2, - }, -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, - MBEDTLS_MD_MD4, - }, -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, - MBEDTLS_MD_MD5, - }, -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, - MBEDTLS_MD_SHA1, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, - MBEDTLS_MD_SHA224, - }, - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, - MBEDTLS_MD_SHA256, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, - MBEDTLS_MD_SHA384, - }, - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, - MBEDTLS_MD_SHA512, - }, -#endif /* MBEDTLS_SHA512_C */ - { - { NULL, 0, NULL, NULL }, - MBEDTLS_MD_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) -#endif /* MBEDTLS_MD_C */ - -#if defined(MBEDTLS_PKCS12_C) -/* - * For PKCS#12 PBEs - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; - mbedtls_cipher_type_t cipher_alg; -} oid_pkcs12_pbe_alg_t; - -static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = -{ - { - { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, - MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, - }, - { - { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, - MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, - }, - { - { NULL, 0, NULL, NULL }, - MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) -FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) -#endif /* MBEDTLS_PKCS12_C */ - -#define OID_SAFE_SNPRINTF \ - do { \ - if( ret < 0 || (size_t) ret >= n ) \ - return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ - \ - n -= (size_t) ret; \ - p += (size_t) ret; \ - } while( 0 ) - -/* Return the x.y.z.... style numeric string for the given OID */ -int mbedtls_oid_get_numeric_string( char *buf, size_t size, - const mbedtls_asn1_buf *oid ) -{ - int ret; - size_t i, n; - unsigned int value; - char *p; - - p = buf; - n = size; - - /* First byte contains first two dots */ - if( oid->len > 0 ) - { - ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); - OID_SAFE_SNPRINTF; - } - - value = 0; - for( i = 1; i < oid->len; i++ ) - { - /* Prevent overflow in value. */ - if( ( ( value << 7 ) >> 7 ) != value ) - return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); - - value <<= 7; - value += oid->p[i] & 0x7F; - - if( !( oid->p[i] & 0x80 ) ) - { - /* Last byte */ - ret = mbedtls_snprintf( p, n, ".%d", value ); - OID_SAFE_SNPRINTF; - value = 0; - } - } - - return( (int) ( size - n ) ); -} - -#endif /* MBEDTLS_OID_C */ diff --git a/components/security/mbedtls/src/padlock.c b/components/security/mbedtls/src/padlock.c deleted file mode 100644 index b85ff9cd..00000000 --- a/components/security/mbedtls/src/padlock.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * VIA PadLock support 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) - */ -/* - * This implementation is based on the VIA PadLock Programming Guide: - * - * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ - * programming_guide.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PADLOCK_C) - -#include "mbedtls/padlock.h" - -#include - -#ifndef asm -#define asm __asm -#endif - -#if defined(MBEDTLS_HAVE_X86) - -/* - * PadLock detection routine - */ -int mbedtls_padlock_has_support( int feature ) -{ - static int flags = -1; - int ebx = 0, edx = 0; - - if( flags == -1 ) - { - asm( "movl %%ebx, %0 \n\t" - "movl $0xC0000000, %%eax \n\t" - "cpuid \n\t" - "cmpl $0xC0000001, %%eax \n\t" - "movl $0, %%edx \n\t" - "jb unsupported \n\t" - "movl $0xC0000001, %%eax \n\t" - "cpuid \n\t" - "unsupported: \n\t" - "movl %%edx, %1 \n\t" - "movl %2, %%ebx \n\t" - : "=m" (ebx), "=m" (edx) - : "m" (ebx) - : "eax", "ecx", "edx" ); - - flags = edx; - } - - return( flags & feature ); -} - -/* - * PadLock AES-ECB block en(de)cryption - */ -int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int ebx = 0; - uint32_t *rk; - uint32_t *blk; - uint32_t *ctrl; - unsigned char buf[256]; - - rk = ctx->rk; - blk = MBEDTLS_PADLOCK_ALIGN16( buf ); - memcpy( blk, input, 16 ); - - ctrl = blk + 4; - *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); - - asm( "pushfl \n\t" - "popfl \n\t" - "movl %%ebx, %0 \n\t" - "movl $1, %%ecx \n\t" - "movl %2, %%edx \n\t" - "movl %3, %%ebx \n\t" - "movl %4, %%esi \n\t" - "movl %4, %%edi \n\t" - ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" - "movl %1, %%ebx \n\t" - : "=m" (ebx) - : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) - : "memory", "ecx", "edx", "esi", "edi" ); - - memcpy( output, blk, 16 ); - - return( 0 ); -} - -/* - * PadLock AES-CBC buffer en(de)cryption - */ -int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int ebx = 0; - size_t count; - uint32_t *rk; - uint32_t *iw; - uint32_t *ctrl; - unsigned char buf[256]; - - if( ( (long) input & 15 ) != 0 || - ( (long) output & 15 ) != 0 ) - return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); - - rk = ctx->rk; - iw = MBEDTLS_PADLOCK_ALIGN16( buf ); - memcpy( iw, iv, 16 ); - - ctrl = iw + 4; - *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); - - count = ( length + 15 ) >> 4; - - asm( "pushfl \n\t" - "popfl \n\t" - "movl %%ebx, %0 \n\t" - "movl %2, %%ecx \n\t" - "movl %3, %%edx \n\t" - "movl %4, %%ebx \n\t" - "movl %5, %%esi \n\t" - "movl %6, %%edi \n\t" - "movl %7, %%eax \n\t" - ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" - "movl %1, %%ebx \n\t" - : "=m" (ebx) - : "m" (ebx), "m" (count), "m" (ctrl), - "m" (rk), "m" (input), "m" (output), "m" (iw) - : "memory", "eax", "ecx", "edx", "esi", "edi" ); - - memcpy( iv, iw, 16 ); - - return( 0 ); -} - -#endif /* MBEDTLS_HAVE_X86 */ - -#endif /* MBEDTLS_PADLOCK_C */ diff --git a/components/security/mbedtls/src/pem.c b/components/security/mbedtls/src/pem.c deleted file mode 100644 index 0358efe4..00000000 --- a/components/security/mbedtls/src/pem.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Privacy Enhanced Mail (PEM) decoding - * - * 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_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) - -#include "mbedtls/pem.h" -#include "mbedtls/base64.h" -#include "mbedtls/des.h" -#include "mbedtls/aes.h" -#include "mbedtls/md5.h" -#include "mbedtls/cipher.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) -/* 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; -} - -void mbedtls_pem_init( mbedtls_pem_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_pem_context ) ); -} - -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) -/* - * Read a 16-byte hex string and convert it to binary - */ -static int pem_get_iv( const unsigned char *s, unsigned char *iv, - size_t iv_len ) -{ - size_t i, j, k; - - memset( iv, 0, iv_len ); - - for( i = 0; i < iv_len * 2; i++, s++ ) - { - if( *s >= '0' && *s <= '9' ) j = *s - '0'; else - if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else - if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else - return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - - k = ( ( i & 1 ) != 0 ) ? j : j << 4; - - iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); - } - - return( 0 ); -} - -static void pem_pbkdf1( unsigned char *key, size_t keylen, - unsigned char *iv, - const unsigned char *pwd, size_t pwdlen ) -{ - mbedtls_md5_context md5_ctx; - unsigned char md5sum[16]; - size_t use_len; - -#if !defined(MBEDTLS_MD5_ALT) - mbedtls_md5_init( &md5_ctx ); - - /* - * key[ 0..15] = MD5(pwd || IV) - */ - mbedtls_md5_starts( &md5_ctx ); - mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); - mbedtls_md5_update( &md5_ctx, iv, 8 ); - mbedtls_md5_finish( &md5_ctx, md5sum ); - - if( keylen <= 16 ) - { - memcpy( key, md5sum, keylen ); - - mbedtls_md5_free( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); - return; - } - - memcpy( key, md5sum, 16 ); - - /* - * key[16..23] = MD5(key[ 0..15] || pwd || IV]) - */ - mbedtls_md5_starts( &md5_ctx ); - mbedtls_md5_update( &md5_ctx, md5sum, 16 ); - mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); - mbedtls_md5_update( &md5_ctx, iv, 8 ); - mbedtls_md5_finish( &md5_ctx, md5sum ); - - use_len = 16; - if( keylen < 32 ) - use_len = keylen - 16; - - memcpy( key + 16, md5sum, use_len ); - - mbedtls_md5_free( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); - -#else /* !MBEDTLS_MD5_ALT */ - - mbedtls_md5_init_alt( &md5_ctx ); - - /* - * key[ 0..15] = MD5(pwd || IV) - */ - mbedtls_md5_starts_alt( &md5_ctx ); - mbedtls_md5_update_alt( &md5_ctx, pwd, pwdlen ); - mbedtls_md5_update_alt( &md5_ctx, iv, 8 ); - mbedtls_md5_finish_alt( &md5_ctx, md5sum ); - - if( keylen <= 16 ) - { - memcpy( key, md5sum, keylen ); - - mbedtls_md5_free_alt( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); - return; - } - - memcpy( key, md5sum, 16 ); - - /* - * key[16..23] = MD5(key[ 0..15] || pwd || IV]) - */ - mbedtls_md5_starts_alt( &md5_ctx ); - mbedtls_md5_update_alt( &md5_ctx, md5sum, 16 ); - mbedtls_md5_update_alt( &md5_ctx, pwd, pwdlen ); - mbedtls_md5_update_alt( &md5_ctx, iv, 8 ); - mbedtls_md5_finish_alt( &md5_ctx, md5sum ); - - use_len = 16; - if( keylen < 32 ) - use_len = keylen - 16; - - memcpy( key + 16, md5sum, use_len ); - - mbedtls_md5_free_alt( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); -#endif /* !MBEDTLS_MD5_ALT */ -} - -#if defined(MBEDTLS_DES_C) -/* - * Decrypt with DES-CBC, using PBKDF1 for key derivation - */ -static void pem_des_decrypt( unsigned char des_iv[8], - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - mbedtls_des_context des_ctx; - unsigned char des_key[8]; - - mbedtls_des_init( &des_ctx ); - - pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); - - mbedtls_des_setkey_dec( &des_ctx, des_key ); - mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, - des_iv, buf, buf ); - - mbedtls_des_free( &des_ctx ); - mbedtls_zeroize( des_key, 8 ); -} - -/* - * Decrypt with 3DES-CBC, using PBKDF1 for key derivation - */ -static void pem_des3_decrypt( unsigned char des3_iv[8], - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - mbedtls_des3_context des3_ctx; - unsigned char des3_key[24]; - - mbedtls_des3_init( &des3_ctx ); - - pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); - - mbedtls_des3_set3key_dec( &des3_ctx, des3_key ); - mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, - des3_iv, buf, buf ); - - mbedtls_des3_free( &des3_ctx ); - mbedtls_zeroize( des3_key, 24 ); -} -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) -/* - * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation - */ -static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - mbedtls_aes_context aes_ctx; - unsigned char aes_key[32]; - -#if !defined(MBEDTLS_AES_ALT) - mbedtls_aes_init( &aes_ctx ); - - pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); - - mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); - mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, - aes_iv, buf, buf ); - - mbedtls_aes_free( &aes_ctx ); - mbedtls_zeroize( aes_key, keylen ); -#else - mbedtls_aes_init_alt( &aes_ctx ); - - pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); - - mbedtls_aes_setkey_dec_alt( &aes_ctx, aes_key, keylen * 8 ); - mbedtls_aes_crypt_cbc_alt( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, - aes_iv, buf, buf ); - - mbedtls_aes_free_alt( &aes_ctx ); - mbedtls_zeroize( aes_key, keylen ); -#endif -} -#endif /* MBEDTLS_AES_C */ - -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - -int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, - const unsigned char *data, const unsigned char *pwd, - size_t pwdlen, size_t *use_len ) -{ - int ret, enc; - size_t len; - unsigned char *buf; - const unsigned char *s1, *s2, *end; -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) - unsigned char pem_iv[16]; - mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; -#else - ((void) pwd); - ((void) pwdlen); -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - - if( ctx == NULL ) - return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); - - s1 = (unsigned char *) strstr( (const char *) data, header ); - - if( s1 == NULL ) - return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - - s2 = (unsigned char *) strstr( (const char *) data, footer ); - - if( s2 == NULL || s2 <= s1 ) - return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - - s1 += strlen( header ); - if( *s1 == ' ' ) s1++; - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - - end = s2; - end += strlen( footer ); - if( *end == ' ' ) end++; - if( *end == '\r' ) end++; - if( *end == '\n' ) end++; - *use_len = end - data; - - enc = 0; - - if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) - { -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) - enc++; - - s1 += 22; - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( MBEDTLS_ERR_PEM_INVALID_DATA ); - - -#if defined(MBEDTLS_DES_C) - if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) - { - enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; - - s1 += 23; - if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) - return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - - s1 += 16; - } - else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) - { - enc_alg = MBEDTLS_CIPHER_DES_CBC; - - s1 += 18; - if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) - return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - - s1 += 16; - } -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) - if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) - { - if( s2 - s1 < 22 ) - return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); - else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) - enc_alg = MBEDTLS_CIPHER_AES_128_CBC; - else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) - enc_alg = MBEDTLS_CIPHER_AES_192_CBC; - else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) - enc_alg = MBEDTLS_CIPHER_AES_256_CBC; - else - return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); - - s1 += 22; - if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) - return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - - s1 += 32; - } -#endif /* MBEDTLS_AES_C */ - - if( enc_alg == MBEDTLS_CIPHER_NONE ) - return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); - - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( MBEDTLS_ERR_PEM_INVALID_DATA ); -#else - return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - } - - if( s1 >= s2 ) - return( MBEDTLS_ERR_PEM_INVALID_DATA ); - - ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); - - if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) - return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); - - if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) - return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); - - if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) - { - mbedtls_free( buf ); - return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); - } - - if( enc != 0 ) - { -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) - if( pwd == NULL ) - { - mbedtls_free( buf ); - return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); - } - -#if defined(MBEDTLS_DES_C) - if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) - pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); - else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) - pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) - if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) - pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); - else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) - pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); - else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) - pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); -#endif /* MBEDTLS_AES_C */ - - /* - * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 - * length bytes (allow 4 to be sure) in all known use cases. - * - * Use that as heurisitic to try detecting password mismatchs. - */ - if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) - { - mbedtls_free( buf ); - return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); - } -#else - mbedtls_free( buf ); - return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - } - - ctx->buf = buf; - ctx->buflen = len; - - return( 0 ); -} - -void mbedtls_pem_free( mbedtls_pem_context *ctx ) -{ - mbedtls_free( ctx->buf ); - mbedtls_free( ctx->info ); - - mbedtls_zeroize( ctx, sizeof( mbedtls_pem_context ) ); -} -#endif /* MBEDTLS_PEM_PARSE_C */ - -#if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_pem_write_buffer( const char *header, const char *footer, - const unsigned char *der_data, size_t der_len, - unsigned char *buf, size_t buf_len, size_t *olen ) -{ - int ret; - unsigned char *encode_buf, *c, *p = buf; - size_t len = 0, use_len, add_len = 0; - - mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); - add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; - - if( use_len + add_len > buf_len ) - { - *olen = use_len + add_len; - return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - if( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) - return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); - - if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, - der_len ) ) != 0 ) - { - mbedtls_free( encode_buf ); - return( ret ); - } - - memcpy( p, header, strlen( header ) ); - p += strlen( header ); - c = encode_buf; - - while( use_len ) - { - len = ( use_len > 64 ) ? 64 : use_len; - memcpy( p, c, len ); - use_len -= len; - p += len; - c += len; - *p++ = '\n'; - } - - memcpy( p, footer, strlen( footer ) ); - p += strlen( footer ); - - *p++ = '\0'; - *olen = p - buf; - - mbedtls_free( encode_buf ); - return( 0 ); -} -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ diff --git a/components/security/mbedtls/src/pk.c b/components/security/mbedtls/src/pk.c deleted file mode 100644 index 8d13bc5c..00000000 --- a/components/security/mbedtls/src/pk.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Public Key abstraction layer - * - * 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.h" -#include "mbedtls/pk_internal.h" - -#include "mbedtls/bignum.h" - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#include - -/* 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; -} - -/* - * Initialise a mbedtls_pk_context - */ -void mbedtls_pk_init( mbedtls_pk_context *ctx ) -{ - if( ctx == NULL ) - return; - - ctx->pk_info = NULL; - ctx->pk_ctx = NULL; -} - -/* - * Free (the components of) a mbedtls_pk_context - */ -void mbedtls_pk_free( mbedtls_pk_context *ctx ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return; - - ctx->pk_info->ctx_free_func( ctx->pk_ctx ); - - mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) ); -} - -/* - * Get pk_info structure from type - */ -const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) -{ - switch( pk_type ) { -#if defined(MBEDTLS_RSA_C) - case MBEDTLS_PK_RSA: - return( &mbedtls_rsa_info ); -#endif -#if defined(MBEDTLS_ECP_C) - case MBEDTLS_PK_ECKEY: - return( &mbedtls_eckey_info ); - case MBEDTLS_PK_ECKEY_DH: - return( &mbedtls_eckeydh_info ); -#endif -#if defined(MBEDTLS_ECDSA_C) - case MBEDTLS_PK_ECDSA: - return( &mbedtls_ecdsa_info ); -#endif - /* MBEDTLS_PK_RSA_ALT omitted on purpose */ - default: - return( NULL ); - } -} - -/* - * Initialise context - */ -int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) -{ - if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - - ctx->pk_info = info; - - return( 0 ); -} - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* - * Initialize an RSA-alt context - */ -int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func ) -{ - mbedtls_rsa_alt_context *rsa_alt; - const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; - - if( ctx == NULL || ctx->pk_info != NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - - ctx->pk_info = info; - - rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; - - rsa_alt->key = key; - rsa_alt->decrypt_func = decrypt_func; - rsa_alt->sign_func = sign_func; - rsa_alt->key_len_func = key_len_func; - - return( 0 ); -} -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/* - * Tell if a PK can do the operations of the given type - */ -int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) -{ - /* null or NONE context can't do anything */ - if( ctx == NULL || ctx->pk_info == NULL ) - return( 0 ); - - return( ctx->pk_info->can_do( type ) ); -} - -/* - * Helper for mbedtls_pk_sign and mbedtls_pk_verify - */ -static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) -{ - const mbedtls_md_info_t *md_info; - - if( *hash_len != 0 ) - return( 0 ); - - if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) - return( -1 ); - - *hash_len = mbedtls_md_get_size( md_info ); - return( 0 ); -} - -/* - * Verify a signature - */ -int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - if( ctx == NULL || ctx->pk_info == NULL || - pk_hashlen_helper( md_alg, &hash_len ) != 0 ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->verify_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len ) ); -} - -/* - * Verify a signature with options - */ -int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ! mbedtls_pk_can_do( ctx, type ) ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - if( type == MBEDTLS_PK_RSASSA_PSS ) - { -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) - int ret; - const mbedtls_pk_rsassa_pss_options *pss_opts; - -#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( options == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; - - if( sig_len < mbedtls_pk_get_len( ctx ) ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), - NULL, NULL, MBEDTLS_RSA_PUBLIC, - md_alg, (unsigned int) hash_len, hash, - pss_opts->mgf1_hash_id, - pss_opts->expected_salt_len, - sig ); - if( ret != 0 ) - return( ret ); - - if( sig_len > mbedtls_pk_get_len( ctx ) ) - return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - - return( 0 ); -#else - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); -#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ - } - - /* General case: no options */ - if( options != NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); -} - -/* - * Make a signature - */ -int mbedtls_pk_sign( mbedtls_pk_context *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( ctx == NULL || ctx->pk_info == NULL || - pk_hashlen_helper( md_alg, &hash_len ) != 0 ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->sign_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len, f_rng, p_rng ) ); -} - -/* - * Decrypt message - */ -int mbedtls_pk_decrypt( mbedtls_pk_context *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( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->decrypt_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, - output, olen, osize, f_rng, p_rng ) ); -} - -/* - * Encrypt message - */ -int mbedtls_pk_encrypt( mbedtls_pk_context *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( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->encrypt_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, - output, olen, osize, f_rng, p_rng ) ); -} - -/* - * Check public-private key pair - */ -int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) -{ - if( pub == NULL || pub->pk_info == NULL || - prv == NULL || prv->pk_info == NULL || - prv->pk_info->check_pair_func == NULL ) - { - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - } - - if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) - { - if( pub->pk_info->type != MBEDTLS_PK_RSA ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - } - else - { - if( pub->pk_info != prv->pk_info ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - } - - return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); -} - -/* - * Get key size in bits - */ -size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( 0 ); - - return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); -} - -/* - * Export debug information - */ -int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->debug_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - ctx->pk_info->debug_func( ctx->pk_ctx, items ); - return( 0 ); -} - -/* - * Access the PK type name - */ -const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( "invalid PK" ); - - return( ctx->pk_info->name ); -} - -/* - * Access the PK type - */ -mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_PK_NONE ); - - return( ctx->pk_info->type ); -} - -#endif /* MBEDTLS_PK_C */ diff --git a/components/security/mbedtls/src/pk_wrap.c b/components/security/mbedtls/src/pk_wrap.c deleted file mode 100644 index 927fa9a8..00000000 --- a/components/security/mbedtls/src/pk_wrap.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * 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 - -#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 -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include - -#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_PK_ALT) -#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 */ - -#else /* MBEDTLS_PK_ALT */ - -static int rsa_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_RSA ); -} - -static size_t rsa_get_bitlen( const void *ctx ) -{ - return( 8 * ((const mbedtls_rsa_context *) ctx)->n_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 ) -{ - return rsa_verify_alt(ctx, (size_t)md_alg, - hash, hash_len, sig, sig_len); -} - -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 ) -{ - (void)f_rng; - (void)p_rng; - - return rsa_sign_alt(ctx, (size_t)md_alg, - hash, hash_len, sig, sig_len); -} - -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 ) -{ - (void)osize; - (void)f_rng; - (void)p_rng; - - if( ilen != ((mbedtls_rsa_context *) ctx)->n_len ) - return -1; - - return rsa_decrypt_alt(ctx, input, ilen, output, olen ); -} - -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 ) -{ - (void)f_rng; - (void)p_rng; - - *olen = ((mbedtls_rsa_context *) ctx)->n_len; - - if( *olen > osize ) - return -1; - - return rsa_encrypt_alt(ctx, input, ilen, output, olen ); -} - -static void *rsa_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); - - if( ctx != NULL ) - mbedtls_rsa_init_alt( (mbedtls_rsa_context *) ctx, 0, 0 ); - - return( ctx ); -} - -static void rsa_free_wrap( void *ctx ) -{ - mbedtls_rsa_free_alt( (mbedtls_rsa_context *) ctx ); - mbedtls_free( ctx ); -} - -static void rsa_debug_wrap( const void *ctx, mbedtls_pk_debug_item *items ) -{ - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.N"; - items->value = ((mbedtls_rsa_context *) ctx)->rsa_n; - - items++; - - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.E"; - items->value = ((mbedtls_rsa_context *) ctx)->rsa_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, - NULL, - rsa_alloc_wrap, - rsa_free_wrap, - rsa_debug_wrap, -}; -#endif /* MBEDTLS_PK_ALT */ - -#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 */ diff --git a/components/security/mbedtls/src/pkcs11.c b/components/security/mbedtls/src/pkcs11.c deleted file mode 100644 index 0ea64252..00000000 --- a/components/security/mbedtls/src/pkcs11.c +++ /dev/null @@ -1,240 +0,0 @@ -/** - * \file pkcs11.c - * - * \brief Wrapper for PKCS#11 library libpkcs11-helper - * - * \author Adriaan de Jong - * - * 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) - */ - -#include "mbedtls/pkcs11.h" - -#if defined(MBEDTLS_PKCS11_C) - -#include "mbedtls/md.h" -#include "mbedtls/oid.h" -#include "mbedtls/x509_crt.h" - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include - -void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); -} - -int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) -{ - int ret = 1; - unsigned char *cert_blob = NULL; - size_t cert_blob_size = 0; - - if( cert == NULL ) - { - ret = 2; - goto cleanup; - } - - if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, - &cert_blob_size ) != CKR_OK ) - { - ret = 3; - goto cleanup; - } - - cert_blob = mbedtls_calloc( 1, cert_blob_size ); - if( NULL == cert_blob ) - { - ret = 4; - goto cleanup; - } - - if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, - &cert_blob_size ) != CKR_OK ) - { - ret = 5; - goto cleanup; - } - - if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) - { - ret = 6; - goto cleanup; - } - - ret = 0; - -cleanup: - if( NULL != cert_blob ) - mbedtls_free( cert_blob ); - - return( ret ); -} - - -int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert ) -{ - int ret = 1; - mbedtls_x509_crt cert; - - mbedtls_x509_crt_init( &cert ); - - if( priv_key == NULL ) - goto cleanup; - - if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) - goto cleanup; - - priv_key->len = mbedtls_pk_get_len( &cert.pk ); - priv_key->pkcs11h_cert = pkcs11_cert; - - ret = 0; - -cleanup: - mbedtls_x509_crt_free( &cert ); - - return( ret ); -} - -void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) -{ - if( NULL != priv_key ) - pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); -} - -int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ) -{ - size_t input_len, output_len; - - if( NULL == ctx ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( MBEDTLS_RSA_PRIVATE != mode ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - output_len = input_len = ctx->len; - - if( input_len < 16 || input_len > output_max_len ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - /* Determine size of output buffer */ - if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, - input_len, NULL, &output_len ) != CKR_OK ) - { - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - } - - if( output_len > output_max_len ) - return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); - - if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, - input_len, output, &output_len ) != CKR_OK ) - { - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - } - *olen = output_len; - return( 0 ); -} - -int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t sig_len = 0, asn_len = 0, oid_size = 0; - unsigned char *p = sig; - const char *oid; - - if( NULL == ctx ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( MBEDTLS_RSA_PRIVATE != mode ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( md_alg != MBEDTLS_MD_NONE ) - { - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hashlen = mbedtls_md_get_size( md_info ); - asn_len = 10 + oid_size; - } - - sig_len = ctx->len; - if( hashlen > sig_len || asn_len > sig_len || - hashlen + asn_len > sig_len ) - { - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - } - - if( md_alg != MBEDTLS_MD_NONE ) - { - /* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x04 + oid_size ); - *p++ = MBEDTLS_ASN1_OID; - *p++ = oid_size & 0xFF; - memcpy( p, oid, oid_size ); - p += oid_size; - *p++ = MBEDTLS_ASN1_NULL; - *p++ = 0x00; - *p++ = MBEDTLS_ASN1_OCTET_STRING; - *p++ = hashlen; - } - - memcpy( p, hash, hashlen ); - - if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, - asn_len + hashlen, sig, &sig_len ) != CKR_OK ) - { - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - } - - return( 0 ); -} - -#endif /* defined(MBEDTLS_PKCS11_C) */ diff --git a/components/security/mbedtls/src/pkcs12.c b/components/security/mbedtls/src/pkcs12.c deleted file mode 100644 index c603a135..00000000 --- a/components/security/mbedtls/src/pkcs12.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * PKCS#12 Personal Information Exchange Syntax - * - * 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) - */ -/* - * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 - * - * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf - * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PKCS12_C) - -#include "mbedtls/pkcs12.h" -#include "mbedtls/asn1.h" -#include "mbedtls/cipher.h" - -#include - -#if defined(MBEDTLS_ARC4_C) -#include "mbedtls/arc4.h" -#endif - -#if defined(MBEDTLS_DES_C) -#include "mbedtls/des.h" -#endif - -/* 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; -} - -static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, - mbedtls_asn1_buf *salt, int *iterations ) -{ - int ret; - unsigned char **p = ¶ms->p; - const unsigned char *end = params->p + params->len; - - /* - * pkcs-12PbeParams ::= SEQUENCE { - * salt OCTET STRING, - * iterations INTEGER - * } - * - */ - if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); - - salt->p = *p; - *p += salt->len; - - if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) - return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); - - if( *p != end ) - return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -#define PKCS12_MAX_PWDLEN 128 - -static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, - const unsigned char *pwd, size_t pwdlen, - unsigned char *key, size_t keylen, - unsigned char *iv, size_t ivlen ) -{ - int ret, iterations = 0; - mbedtls_asn1_buf salt; - size_t i; - unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; - - if( pwdlen > PKCS12_MAX_PWDLEN ) - return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); - - memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); - memset( &unipwd, 0, sizeof(unipwd) ); - - if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, - &iterations ) ) != 0 ) - return( ret ); - - for( i = 0; i < pwdlen; i++ ) - unipwd[i * 2 + 1] = pwd[i]; - - if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, - salt.p, salt.len, md_type, - MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) - { - return( ret ); - } - - if( iv == NULL || ivlen == 0 ) - return( 0 ); - - if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, - salt.p, salt.len, md_type, - MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) - { - return( ret ); - } - return( 0 ); -} - -#undef PKCS12_MAX_PWDLEN - -int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t len, - unsigned char *output ) -{ -#if !defined(MBEDTLS_ARC4_C) - ((void) pbe_params); - ((void) mode); - ((void) pwd); - ((void) pwdlen); - ((void) data); - ((void) len); - ((void) output); - return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); -#else - int ret; - unsigned char key[16]; - mbedtls_arc4_context ctx; - ((void) mode); - - mbedtls_arc4_init( &ctx ); - - if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, - pwd, pwdlen, - key, 16, NULL, 0 ) ) != 0 ) - { - return( ret ); - } - - mbedtls_arc4_setup( &ctx, key, 16 ); - if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) - goto exit; - -exit: - mbedtls_zeroize( key, sizeof( key ) ); - mbedtls_arc4_free( &ctx ); - - return( ret ); -#endif /* MBEDTLS_ARC4_C */ -} - -int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, - mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t len, - unsigned char *output ) -{ - int ret, keylen = 0; - unsigned char key[32]; - unsigned char iv[16]; - const mbedtls_cipher_info_t *cipher_info; - mbedtls_cipher_context_t cipher_ctx; - size_t olen = 0; - - cipher_info = mbedtls_cipher_info_from_type( cipher_type ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); - - keylen = cipher_info->key_bitlen / 8; - - if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, - key, keylen, - iv, cipher_info->iv_size ) ) != 0 ) - { - return( ret ); - } - - mbedtls_cipher_init( &cipher_ctx ); - - if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, - output, &olen ) ) != 0 ) - { - goto exit; - } - - if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) - ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; - -exit: - mbedtls_zeroize( key, sizeof( key ) ); - mbedtls_zeroize( iv, sizeof( iv ) ); - mbedtls_cipher_free( &cipher_ctx ); - - return( ret ); -} - -static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, - const unsigned char *filler, size_t fill_len ) -{ - unsigned char *p = data; - size_t use_len; - - while( data_len > 0 ) - { - use_len = ( data_len > fill_len ) ? fill_len : data_len; - memcpy( p, filler, use_len ); - p += use_len; - data_len -= use_len; - } -} - -int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *salt, size_t saltlen, - mbedtls_md_type_t md_type, int id, int iterations ) -{ - int ret; - unsigned int j; - - unsigned char diversifier[128]; - unsigned char salt_block[128], pwd_block[128], hash_block[128]; - unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; - unsigned char *p; - unsigned char c; - - size_t hlen, use_len, v, i; - - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - // This version only allows max of 64 bytes of password or salt - if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) - return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); - - md_info = mbedtls_md_info_from_type( md_type ); - if( md_info == NULL ) - return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); - - mbedtls_md_init( &md_ctx ); - - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - return( ret ); - hlen = mbedtls_md_get_size( md_info ); - - if( hlen <= 32 ) - v = 64; - else - v = 128; - - memset( diversifier, (unsigned char) id, v ); - - pkcs12_fill_buffer( salt_block, v, salt, saltlen ); - pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); - - p = data; - while( datalen > 0 ) - { - // Calculate hash( diversifier || salt_block || pwd_block ) - if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) - goto exit; - - // Perform remaining ( iterations - 1 ) recursive hash calculations - for( i = 1; i < (size_t) iterations; i++ ) - { - if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) - goto exit; - } - - use_len = ( datalen > hlen ) ? hlen : datalen; - memcpy( p, hash_output, use_len ); - datalen -= use_len; - p += use_len; - - if( datalen == 0 ) - break; - - // Concatenating copies of hash_output into hash_block (B) - pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); - - // B += 1 - for( i = v; i > 0; i-- ) - if( ++hash_block[i - 1] != 0 ) - break; - - // salt_block += B - c = 0; - for( i = v; i > 0; i-- ) - { - j = salt_block[i - 1] + hash_block[i - 1] + c; - c = (unsigned char) (j >> 8); - salt_block[i - 1] = j & 0xFF; - } - - // pwd_block += B - c = 0; - for( i = v; i > 0; i-- ) - { - j = pwd_block[i - 1] + hash_block[i - 1] + c; - c = (unsigned char) (j >> 8); - pwd_block[i - 1] = j & 0xFF; - } - } - - ret = 0; - -exit: - mbedtls_zeroize( salt_block, sizeof( salt_block ) ); - mbedtls_zeroize( pwd_block, sizeof( pwd_block ) ); - mbedtls_zeroize( hash_block, sizeof( hash_block ) ); - mbedtls_zeroize( hash_output, sizeof( hash_output ) ); - - mbedtls_md_free( &md_ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_PKCS12_C */ diff --git a/components/security/mbedtls/src/pkcs5.c b/components/security/mbedtls/src/pkcs5.c deleted file mode 100644 index e28d5a84..00000000 --- a/components/security/mbedtls/src/pkcs5.c +++ /dev/null @@ -1,406 +0,0 @@ -/** - * \file pkcs5.c - * - * \brief PKCS#5 functions - * - * \author Mathias Olsson - * - * 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) - */ -/* - * PKCS#5 includes PBKDF2 and more - * - * http://tools.ietf.org/html/rfc2898 (Specification) - * http://tools.ietf.org/html/rfc6070 (Test vectors) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PKCS5_C) - -#include "mbedtls/pkcs5.h" -#include "mbedtls/asn1.h" -#include "mbedtls/cipher.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif - -static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, - mbedtls_asn1_buf *salt, int *iterations, - int *keylen, mbedtls_md_type_t *md_type ) -{ - int ret; - mbedtls_asn1_buf prf_alg_oid; - unsigned char *p = params->p; - const unsigned char *end = params->p + params->len; - - if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - /* - * PBKDF2-params ::= SEQUENCE { - * salt OCTET STRING, - * iterationCount INTEGER, - * keyLength INTEGER OPTIONAL - * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 - * } - * - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - - salt->p = p; - p += salt->len; - - if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - - if( p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) - { - if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - } - - if( p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - - if( MBEDTLS_OID_CMP( MBEDTLS_OID_HMAC_SHA1, &prf_alg_oid ) != 0 ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - *md_type = MBEDTLS_MD_SHA1; - - if( p != end ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t datalen, - unsigned char *output ) -{ - int ret, iterations = 0, keylen = 0; - unsigned char *p, *end; - mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; - mbedtls_asn1_buf salt; - mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; - unsigned char key[32], iv[32]; - size_t olen = 0; - const mbedtls_md_info_t *md_info; - const mbedtls_cipher_info_t *cipher_info; - mbedtls_md_context_t md_ctx; - mbedtls_cipher_type_t cipher_alg; - mbedtls_cipher_context_t cipher_ctx; - - p = pbe_params->p; - end = p + pbe_params->len; - - /* - * PBES2-params ::= SEQUENCE { - * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, - * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} - * } - */ - if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - - // Only PBKDF2 supported at the moment - // - if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, - &salt, &iterations, &keylen, - &md_type ) ) != 0 ) - { - return( ret ); - } - - md_info = mbedtls_md_info_from_type( md_type ); - if( md_info == NULL ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, - &enc_scheme_params ) ) != 0 ) - { - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - } - - if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - /* - * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored - * since it is optional and we don't know if it was set or not - */ - keylen = cipher_info->key_bitlen / 8; - - if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || - enc_scheme_params.len != cipher_info->iv_size ) - { - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); - } - - mbedtls_md_init( &md_ctx ); - mbedtls_cipher_init( &cipher_ctx ); - - memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); - - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, - iterations, keylen, key ) ) != 0 ) - { - goto exit; - } - - if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, - data, datalen, output, &olen ) ) != 0 ) - ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; - -exit: - mbedtls_md_free( &md_ctx ); - mbedtls_cipher_free( &cipher_ctx ); - - return( ret ); -} - -int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, - size_t plen, const unsigned char *salt, size_t slen, - unsigned int iteration_count, - uint32_t key_length, unsigned char *output ) -{ - int ret, j; - unsigned int i; - unsigned char md1[MBEDTLS_MD_MAX_SIZE]; - unsigned char work[MBEDTLS_MD_MAX_SIZE]; - unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); - size_t use_len; - unsigned char *out_p = output; - unsigned char counter[4]; - - memset( counter, 0, 4 ); - counter[3] = 1; - - if( iteration_count > 0xFFFFFFFF ) - return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); - - while( key_length ) - { - // U1 ends up in work - // - if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) - return( ret ); - - memcpy( md1, work, md_size ); - - for( i = 1; i < iteration_count; i++ ) - { - // U2 ends up in md1 - // - if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) - return( ret ); - - // U1 xor U2 - // - for( j = 0; j < md_size; j++ ) - work[j] ^= md1[j]; - } - - use_len = ( key_length < md_size ) ? key_length : md_size; - memcpy( out_p, work, use_len ); - - key_length -= (uint32_t) use_len; - out_p += use_len; - - for( i = 4; i > 0; i-- ) - if( ++counter[i - 1] != 0 ) - break; - } - - return( 0 ); -} - -#if defined(MBEDTLS_SELF_TEST) - -#if !defined(MBEDTLS_SHA1_C) -int mbedtls_pkcs5_self_test( int verbose ) -{ - if( verbose != 0 ) - mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); - - return( 0 ); -} -#else - -#define MAX_TESTS 6 - -static const size_t plen[MAX_TESTS] = - { 8, 8, 8, 24, 9 }; - -static const unsigned char password[MAX_TESTS][32] = -{ - "password", - "password", - "password", - "passwordPASSWORDpassword", - "pass\0word", -}; - -static const size_t slen[MAX_TESTS] = - { 4, 4, 4, 36, 5 }; - -static const unsigned char salt[MAX_TESTS][40] = -{ - "salt", - "salt", - "salt", - "saltSALTsaltSALTsaltSALTsaltSALTsalt", - "sa\0lt", -}; - -static const uint32_t it_cnt[MAX_TESTS] = - { 1, 2, 4096, 4096, 4096 }; - -static const uint32_t key_len[MAX_TESTS] = - { 20, 20, 20, 25, 16 }; - -static const unsigned char result_key[MAX_TESTS][32] = -{ - { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, - 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, - 0x2f, 0xe0, 0x37, 0xa6 }, - { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, - 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, - 0xd8, 0xde, 0x89, 0x57 }, - { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, - 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, - 0x65, 0xa4, 0x29, 0xc1 }, - { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, - 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, - 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, - 0x38 }, - { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, - 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, -}; - -int mbedtls_pkcs5_self_test( int verbose ) -{ - mbedtls_md_context_t sha1_ctx; - const mbedtls_md_info_t *info_sha1; - int ret, i; - unsigned char key[64]; - - mbedtls_md_init( &sha1_ctx ); - - info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); - if( info_sha1 == NULL ) - { - ret = 1; - goto exit; - } - - if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) - { - ret = 1; - goto exit; - } - - for( i = 0; i < MAX_TESTS; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); - - ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], - slen[i], it_cnt[i], key_len[i], key ); - if( ret != 0 || - memcmp( result_key[i], key, key_len[i] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_md_free( &sha1_ctx ); - - return( ret ); -} -#endif /* MBEDTLS_SHA1_C */ - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_PKCS5_C */ diff --git a/components/security/mbedtls/src/pkparse.c b/components/security/mbedtls/src/pkparse.c deleted file mode 100644 index 24f2451c..00000000 --- a/components/security/mbedtls/src/pkparse.c +++ /dev/null @@ -1,1399 +0,0 @@ -/* - * Public Key layer for parsing key files and structures - * - * 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) - */ - -#include -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PK_PARSE_C) - -#include "mbedtls/pk.h" -#include "mbedtls/asn1.h" -#include "mbedtls/oid.h" -#include "mbedtls/debug.h" - -#include - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif -#if defined(MBEDTLS_PKCS5_C) -#include "mbedtls/pkcs5.h" -#endif -#if defined(MBEDTLS_PKCS12_C) -#include "mbedtls/pkcs12.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_IOT_SPECIFIC) -static unsigned char CRT_OID_PKCS1_RSA[] = { - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 -}; -#endif - -#if defined(MBEDTLS_FS_IO) -/* 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; -} - -/* - * Load all data from a file into a given buffer. - * - * The file is expected to contain either PEM or DER encoded data. - * A terminating null byte is always appended. It is included in the announced - * length only if the data looks like it is PEM encoded. - */ -int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) -{ -#if 0 - FILE *f; - long size; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - if( ( size = ftell( f ) ) == -1 ) - { - fclose( f ); - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); - } - fseek( f, 0, SEEK_SET ); - - *n = (size_t) size; - - if( *n + 1 == 0 || - ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) - { - fclose( f ); - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - } - - if( fread( *buf, 1, *n, f ) != *n ) - { - fclose( f ); - mbedtls_free( *buf ); - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); - } - - fclose( f ); - - (*buf)[*n] = '\0'; -#else - off_t size; - int fd; - - printf("Open path %s\r\n", path); - fd = aos_open(path, 0); - if (fd < 0) { - printf("%s:%d\r\n", __func__, __LINE__); - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - - size = aos_lseek(fd, 0, SEEK_END); - if (-1 == size) { - aos_close(fd); - printf("%s:%d\r\n", __func__, __LINE__); - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - aos_lseek(fd, 0, SEEK_SET); - - *n = (size_t)size; - - printf("Cert size is %d\r\n", *n); - if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL ) { - aos_close(fd); - printf("%s:%d\r\n", __func__, __LINE__); - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - if (aos_read(fd, *buf, *n) != *n) { - aos_close(fd); - mbedtls_free(*buf); - printf("%s:%d\r\n", __func__, __LINE__); - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - aos_close(fd); - - (*buf)[*n] = '\0'; - if (strstr((const char *) *buf, "-----BEGIN " ) != NULL) { - ++*n; - } - - return 0; -#endif -} - -/* - * Load and parse a private key - */ -int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, - const char *path, const char *pwd ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - if( pwd == NULL ) - ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); - else - ret = mbedtls_pk_parse_key( ctx, buf, n, - (const unsigned char *) pwd, strlen( pwd ) ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} - -/* - * Load and parse a public key - */ -int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_pk_parse_public_key( ctx, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_ECP_C) -/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - * } - */ -static int pk_get_ecparams( unsigned char **p, const unsigned char *end, - mbedtls_asn1_buf *params ) -{ - int ret; - - /* Tag may be either OID or SEQUENCE */ - params->tag = **p; - if( params->tag != MBEDTLS_ASN1_OID -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) -#endif - ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - } - - if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - params->p = *p; - *p += params->len; - - if( *p != end ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) -/* - * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. - * WARNING: the resulting group should only be used with - * pk_group_id_from_specified(), since its base point may not be set correctly - * if it was encoded compressed. - * - * SpecifiedECDomain ::= SEQUENCE { - * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), - * fieldID FieldID {{FieldTypes}}, - * curve Curve, - * base ECPoint, - * order INTEGER, - * cofactor INTEGER OPTIONAL, - * hash HashAlgorithm OPTIONAL, - * ... - * } - * - * We only support prime-field as field type, and ignore hash and cofactor. - */ -static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) -{ - int ret; - unsigned char *p = params->p; - const unsigned char * const end = params->p + params->len; - const unsigned char *end_field, *end_curve; - size_t len; - int ver; - - /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ - if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ver < 1 || ver > 3 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - - /* - * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field - * fieldType FIELD-ID.&id({IOSet}), - * parameters FIELD-ID.&Type({IOSet}{@fieldType}) - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - end_field = p + len; - - /* - * FIELD-ID ::= TYPE-IDENTIFIER - * FieldTypes FIELD-ID ::= { - * { Prime-p IDENTIFIED BY prime-field } | - * { Characteristic-two IDENTIFIED BY characteristic-two-field } - * } - * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( ret ); - - if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || - memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) - { - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - } - - p += len; - - /* Prime-p ::= INTEGER -- Field of size p. */ - if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - - if( p != end_field ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - /* - * Curve ::= SEQUENCE { - * a FieldElement, - * b FieldElement, - * seed BIT STRING OPTIONAL - * -- Shall be present if used in SpecifiedECDomain - * -- with version equal to ecdpVer2 or ecdpVer3 - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - end_curve = p + len; - - /* - * FieldElement ::= OCTET STRING - * containing an integer in the case of a prime field - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || - ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - p += len; - - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || - ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - p += len; - - /* Ignore seed BIT STRING OPTIONAL */ - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) - p += len; - - if( p != end_curve ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - /* - * ECPoint ::= OCTET STRING - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, - ( const unsigned char *) p, len ) ) != 0 ) - { - /* - * If we can't read the point because it's compressed, cheat by - * reading only the X coordinate and the parity bit of Y. - */ - if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || - ( p[0] != 0x02 && p[0] != 0x03 ) || - len != mbedtls_mpi_size( &grp->P ) + 1 || - mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || - mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || - mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - } - } - - p += len; - - /* - * order INTEGER - */ - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - grp->nbits = mbedtls_mpi_bitlen( &grp->N ); - - /* - * Allow optional elements by purposefully not enforcing p == end here. - */ - - return( 0 ); -} - -/* - * Find the group id associated with an (almost filled) group as generated by - * pk_group_from_specified(), or return an error if unknown. - */ -static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) -{ - int ret = 0; - mbedtls_ecp_group ref; - const mbedtls_ecp_group_id *id; - - mbedtls_ecp_group_init( &ref ); - - for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) - { - /* Load the group associated to that id */ - mbedtls_ecp_group_free( &ref ); - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); - - /* Compare to the group we were given, starting with easy tests */ - if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && - mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && - /* For Y we may only know the parity bit, so compare only that */ - mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) - { - break; - } - - } - -cleanup: - mbedtls_ecp_group_free( &ref ); - - *grp_id = *id; - - if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - - return( ret ); -} - -/* - * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID - */ -static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, - mbedtls_ecp_group_id *grp_id ) -{ - int ret; - mbedtls_ecp_group grp; - - mbedtls_ecp_group_init( &grp ); - - if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) - goto cleanup; - - ret = pk_group_id_from_group( &grp, grp_id ); - -cleanup: - mbedtls_ecp_group_free( &grp ); - - return( ret ); -} -#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ - -/* - * Use EC parameters to initialise an EC group - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - */ -static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) -{ - int ret; - mbedtls_ecp_group_id grp_id; - - if( params->tag == MBEDTLS_ASN1_OID ) - { - if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) - return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); - } - else - { -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) - return( ret ); -#else - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); -#endif - } - - /* - * grp may already be initilialized; if so, make sure IDs match - */ - if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - - if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * EC public key is an EC point - * - * The caller is responsible for clearing the structure upon failure if - * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE - * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. - */ -static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, - mbedtls_ecp_keypair *key ) -{ - int ret; - - if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, - (const unsigned char *) *p, end - *p ) ) == 0 ) - { - ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); - } - - /* - * We know mbedtls_ecp_point_read_binary consumed all bytes or failed - */ - *p = (unsigned char *) end; - - return( ret ); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_get_rsapubkey( unsigned char **p, - const unsigned char *end, - mbedtls_rsa_context *rsa ) -{ - int ret; - size_t len; -#if defined(MBEDTLS_PK_ALT) - int n_len; - int e_len; - unsigned char *rsa_n; - unsigned char *rsa_e; -#endif - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - -#if defined(MBEDTLS_PK_ALT) - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) - return( ret ); - - rsa_n = *p; - n_len = len; - *p += len; - - while(*rsa_n == 0x00) { - rsa_n++; - n_len--; - } - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) - return( ret ); - - rsa_e = *p; - e_len = len; - *p += len; - - rsa->n_len = n_len; - rsa->e_len = e_len; - rsa->rsa_n = rsa_n; - rsa->rsa_e = rsa_e; - - MBEDTLS_ALT_DEBUG_BUF(3, "rsa_n", rsa->rsa_n, rsa->n_len); - MBEDTLS_ALT_DEBUG_BUF(3, "rsa_e", rsa->rsa_e, rsa->e_len); - -#else /* MBEDTLS_PK_ALT */ - - if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); - - if( *p != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); - - rsa->len = mbedtls_mpi_size( &rsa->N ); -#endif /* MBEDTLS_PK_ALT */ - - return( 0 ); -} -#endif /* MBEDTLS_RSA_C */ - -/* Get a PK algorithm identifier - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - */ -static int pk_get_pk_alg( unsigned char **p, - const unsigned char *end, - mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) -{ - int ret; - mbedtls_asn1_buf alg_oid; - - memset( params, 0, sizeof(mbedtls_asn1_buf) ); - - if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); - - -#if defined(MBEDTLS_IOT_SPECIFIC) - if( alg_oid.len != CRT_OID_IDENT_LEN || - memcmp(alg_oid.p, CRT_OID_PKCS1_RSA, CRT_OID_IDENT_LEN ) ) { - MBEDTLS_ALT_DEBUG_BUF(1, "pk_alg_oid", alg_oid.p, alg_oid.len); - return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); - } else { - *pk_alg = MBEDTLS_PK_RSA; - } -#else - if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); -#endif /* MBEDTLS_IOT_SPECIFIC */ - - /* - * No parameters with RSA (only for EC) - */ - if( *pk_alg == MBEDTLS_PK_RSA && - ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || - params->len != 0 ) ) - { - return( MBEDTLS_ERR_PK_INVALID_ALG ); - } - - return( 0 ); -} - -/* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ -int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk ) -{ - int ret; - size_t len; - mbedtls_asn1_buf alg_params; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = *p + len; - - if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_RSA_C) - if( pk_alg == MBEDTLS_PK_RSA ) - { - ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) - { - ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); - if( ret == 0 ) - ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); - } else -#endif /* MBEDTLS_ECP_C */ - ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - - if( ret == 0 && *p != end ) - ret = MBEDTLS_ERR_PK_INVALID_PUBKEY - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - - if( ret != 0 ) - mbedtls_pk_free( pk ); - - return( ret ); -} - -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_RSA_PRIV_ENABLED) -/* - * Parse a PKCS#1 encoded private RSA key - */ -static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, - const unsigned char *key, - size_t keylen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - - p = (unsigned char *) key; - end = p + keylen; - - /* - * This function parses the RSAPrivateKey (PKCS#1) - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * otherPrimeInfos OtherPrimeInfos OPTIONAL - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - if( rsa->ver != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); - } - - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) - { - mbedtls_rsa_free( rsa ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - rsa->len = mbedtls_mpi_size( &rsa->N ); - - if( p != end ) - { - mbedtls_rsa_free( rsa ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 ) - { - mbedtls_rsa_free( rsa ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_RSA_PRIV_ENABLED */ -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * Parse a SEC1 encoded private EC key - */ -static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, - const unsigned char *key, - size_t keylen ) -{ - int ret; - int version, pubkey_done; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - unsigned char *end2; - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( version != 1 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - p += len; - - pubkey_done = 0; - if( p != end ) - { - /* - * Is 'parameters' present? - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) - { - if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || - ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( ret ); - } - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - /* - * Is 'publickey' present? If not, or if we can't read it (eg because it - * is compressed), create it from the private key. - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) - { - end2 = p + len; - - if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( p + len != end2 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) - pubkey_done = 1; - else - { - /* - * The only acceptable failure mode of pk_get_ecpubkey() above - * is if the point format is not recognized. - */ - if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - } - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - } - - if( ! pubkey_done && - ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, - NULL, NULL ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_ECP_C */ - -/* - * Parse an unencrypted PKCS#8 encoded private key - */ -static int pk_parse_key_pkcs8_unencrypted_der( - mbedtls_pk_context *pk, - const unsigned char* key, - size_t keylen ) -{ - int ret, version; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; - - /* - * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL } - * - * Version ::= INTEGER - * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - * PrivateKey ::= OCTET STRING - * - * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey - */ - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( version != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); - - if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( len < 1 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_RSA_PRIV_ENABLED) - if( pk_alg == MBEDTLS_PK_RSA ) - { - if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) - { - mbedtls_pk_free( pk ); - return( ret ); - } - } else -#endif /* MBEDTLS_RSA_PRIV_ENABLED */ -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) - { - if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) - { - mbedtls_pk_free( pk ); - return( ret ); - } - } else -#endif /* MBEDTLS_ECP_C */ - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - return( 0 ); -} - -/* - * Parse an encrypted PKCS#8 encoded private key - */ -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) -static int pk_parse_key_pkcs8_encrypted_der( - mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) -{ - int ret, decrypted = 0; - size_t len; - unsigned char buf[2048]; - unsigned char *p, *end; - mbedtls_asn1_buf pbe_alg_oid, pbe_params; -#if defined(MBEDTLS_PKCS12_C) - mbedtls_cipher_type_t cipher_alg; - mbedtls_md_type_t md_alg; -#endif - - memset( buf, 0, sizeof( buf ) ); - - p = (unsigned char *) key; - end = p + keylen; - - if( pwdlen == 0 ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); - - /* - * This function parses the EncryptedPrivatKeyInfo object (PKCS#8) - * - * EncryptedPrivateKeyInfo ::= SEQUENCE { - * encryptionAlgorithm EncryptionAlgorithmIdentifier, - * encryptedData EncryptedData - * } - * - * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * EncryptedData ::= OCTET STRING - * - * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( len > sizeof( buf ) ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - /* - * Decrypt EncryptedData with appropriate PDE - */ -#if defined(MBEDTLS_PKCS12_C) - if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) - { - if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, - cipher_alg, md_alg, - pwd, pwdlen, p, len, buf ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - - return( ret ); - } - - decrypted = 1; - } - else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) - { - if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, - MBEDTLS_PKCS12_PBE_DECRYPT, - pwd, pwdlen, - p, len, buf ) ) != 0 ) - { - return( ret ); - } - - // Best guess for password mismatch when using RC4. If first tag is - // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE - // - if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - - decrypted = 1; - } - else -#endif /* MBEDTLS_PKCS12_C */ -#if defined(MBEDTLS_PKCS5_C) - if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) - { - if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, - p, len, buf ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - - return( ret ); - } - - decrypted = 1; - } - else -#endif /* MBEDTLS_PKCS5_C */ - { - ((void) pwd); - } - - if( decrypted == 0 ) - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - - return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); -} -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - -/* - * Parse a private key - */ -int mbedtls_pk_parse_key( mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) -{ - int ret; - const mbedtls_pk_info_t *pk_info; - -#if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; - - mbedtls_pem_init( &pem ); - -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_RSA_PRIV_ENABLED) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", - key, pwd, pwdlen, &len ); - - if( ret == 0 ) - { - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); - } - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); -#else - (void)pwd; - (void)pwdlen; - (void)pk_info; -#endif /* MBEDTLS_RSA_PRIV_ENABLED */ -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN EC PRIVATE KEY-----", - "-----END EC PRIVATE KEY-----", - key, pwd, pwdlen, &len ); - if( ret == 0 ) - { - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); - } - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); -#endif /* MBEDTLS_ECP_C */ - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN PRIVATE KEY-----", - "-----END PRIVATE KEY-----", - key, NULL, 0, &len ); - if( ret == 0 ) - { - if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); - -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN ENCRYPTED PRIVATE KEY-----", - "-----END ENCRYPTED PRIVATE KEY-----", - key, NULL, 0, &len ); - if( ret == 0 ) - { - if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, - pem.buf, pem.buflen, - pwd, pwdlen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ -#else - ((void) ret); - ((void) pwd); - ((void) pwdlen); -#endif /* MBEDTLS_PEM_PARSE_C */ - - /* - * At this point we only know it's not a PEM formatted key. Could be any - * of the known DER encoded private key formats - * - * We try the different DER format parsers to see if one passes without - * error - */ -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, - pwd, pwdlen ) ) == 0 ) - { - return( 0 ); - } - - mbedtls_pk_free( pk ); - - if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) - { - return( ret ); - } -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - - if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) - return( 0 ); - - mbedtls_pk_free( pk ); - -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_RSA_PRIV_ENABLED) - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 ) - { - return( 0 ); - } - - mbedtls_pk_free( pk ); -#endif /* MBEDTLS_RSA_PRIV_ENABLED */ -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 ) - { - return( 0 ); - } - - mbedtls_pk_free( pk ); -#endif /* MBEDTLS_ECP_C */ - - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); -} - -/* - * Parse a public key - */ -int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen ) -{ - int ret; - unsigned char *p; -#if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; - - mbedtls_pem_init( &pem ); - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN PUBLIC KEY-----", - "-----END PUBLIC KEY-----", - key, NULL, 0, &len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - key = pem.buf; - keylen = pem.buflen; - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } -#endif /* MBEDTLS_PEM_PARSE_C */ - p = (unsigned char *) key; - - ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); - -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_free( &pem ); -#endif - - return( ret ); -} - -#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/components/security/mbedtls/src/pkwrite.c b/components/security/mbedtls/src/pkwrite.c deleted file mode 100644 index 83b798c1..00000000 --- a/components/security/mbedtls/src/pkwrite.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Public Key layer for writing key files and structures - * - * 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_WRITE_C) - -#include "mbedtls/pk.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, - mbedtls_rsa_context *rsa ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->E ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->N ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * EC public key is an EC point - */ -static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec ) -{ - int ret; - size_t len = 0; - unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; - - if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - &len, buf, sizeof( buf ) ) ) != 0 ) - { - return( ret ); - } - - if( *p < start || (size_t)( *p - start ) < len ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *p -= len; - memcpy( *p, buf, len ); - - return( (int) len ); -} - -/* - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * } - */ -static int pk_write_ec_param( unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec ) -{ - int ret; - size_t len = 0; - const char *oid; - size_t oid_len; - - if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) - return( ret ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); - - return( (int) len ); -} -#endif /* MBEDTLS_ECP_C */ - -int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key ) -{ - int ret; - size_t len = 0; - -#if defined(MBEDTLS_RSA_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) - MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); - else -#endif -#if defined(MBEDTLS_ECP_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) - MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); - else -#endif - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - - return( (int) len ); -} - -int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) -{ - int ret; - unsigned char *c; - size_t len = 0, par_len = 0, oid_len; - const char *oid; - - c = buf + size; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); - - if( c - buf < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - /* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ - *--c = 0; - len += 1; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); - - if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ), - &oid, &oid_len ) ) != 0 ) - { - return( ret ); - } - -#if defined(MBEDTLS_ECP_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) - { - MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); - } -#endif - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, - par_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) -{ - int ret; - unsigned char *c = buf + size; - size_t len = 0; - -#if defined(MBEDTLS_RSA_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) - { - mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - } - else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) - { - mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); - size_t pub_len = 0, par_len = 0; - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - - /* publicKey */ - MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); - - if( c - buf < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - *--c = 0; - pub_len += 1; - - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); - - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); - len += pub_len; - - /* parameters */ - MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); - - MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); - MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); - len += par_len; - - /* privateKey: write as MPI then fix tag */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) ); - *c = MBEDTLS_ASN1_OCTET_STRING; - - /* version */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - } - else -#endif /* MBEDTLS_ECP_C */ - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - - return( (int) len ); -} - -#if defined(MBEDTLS_PEM_WRITE_C) - -#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" -#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" - -#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" -#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" - -/* - * Max sizes of key per types. Shown as tag + len (+ content). - */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSA public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 9 (rsa oid) - * + 1 + 1 (params null) - * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) - * RSAPublicKey ::= SEQUENCE { 1 + 3 - * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 - * } - */ -#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE - -/* - * RSA private keys: - * RSAPrivateKey ::= SEQUENCE { 1 + 3 - * version Version, 1 + 1 + 1 - * modulus INTEGER, 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 - * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 - * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) - * } - */ -#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ - MBEDTLS_MPI_MAX_SIZE % 2 -#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ - + 5 * MPI_MAX_SIZE_2 - -#else /* MBEDTLS_RSA_C */ - -#define RSA_PUB_DER_MAX_BYTES 0 -#define RSA_PRV_DER_MAX_BYTES 0 - -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * EC public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 7 (ec oid) - * + 1 + 1 + 9 (namedCurve oid) - * subjectPublicKey BIT STRING 1 + 2 + 1 [1] - * + 1 (point format) [1] - * + 2 * ECP_MAX (coords) [1] - * } - */ -#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES - -/* - * EC private keys: - * ECPrivateKey ::= SEQUENCE { 1 + 2 - * version INTEGER , 1 + 1 + 1 - * privateKey OCTET STRING, 1 + 1 + ECP_MAX - * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) - * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above - * } - */ -#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES - -#else /* MBEDTLS_ECP_C */ - -#define ECP_PUB_DER_MAX_BYTES 0 -#define ECP_PRV_DER_MAX_BYTES 0 - -#endif /* MBEDTLS_ECP_C */ - -#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ - RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES -#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ - RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES - -int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) -{ - int ret; - unsigned char output_buf[PUB_DER_MAX_BYTES]; - size_t olen = 0; - - if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, - sizeof(output_buf) ) ) < 0 ) - { - return( ret ); - } - - if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} - -int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) -{ - int ret; - unsigned char output_buf[PRV_DER_MAX_BYTES]; - const char *begin, *end; - size_t olen = 0; - - if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) - return( ret ); - -#if defined(MBEDTLS_RSA_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) - { - begin = PEM_BEGIN_PRIVATE_KEY_RSA; - end = PEM_END_PRIVATE_KEY_RSA; - } - else -#endif -#if defined(MBEDTLS_ECP_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) - { - begin = PEM_BEGIN_PRIVATE_KEY_EC; - end = PEM_END_PRIVATE_KEY_EC; - } - else -#endif - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - - if( ( ret = mbedtls_pem_write_buffer( begin, end, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/components/security/mbedtls/src/platform.c b/components/security/mbedtls/src/platform.c deleted file mode 100644 index b957135d..00000000 --- a/components/security/mbedtls/src/platform.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Platform abstraction layer - * - * Copyright (C) 2006-2016, 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_PLATFORM_C) && !defined(MBEDTLS_PLATFORM_ALT) - -#include "mbedtls/platform.h" - -#if defined(MBEDTLS_PLATFORM_MEMORY) -#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) -static void *platform_calloc_uninit( size_t n, size_t size ) -{ - ((void) n); - ((void) size); - return( NULL ); -} - -#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit -#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ - -#if !defined(MBEDTLS_PLATFORM_STD_FREE) -static void platform_free_uninit( void *ptr ) -{ - ((void) ptr); -} - -#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit -#endif /* !MBEDTLS_PLATFORM_STD_FREE */ - -void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; -void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; - -int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), - void (*free_func)( void * ) ) -{ - mbedtls_calloc = calloc_func; - mbedtls_free = free_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_MEMORY */ - -#if defined(_WIN32) -#include -int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) -{ - int ret; - va_list argp; - - /* Avoid calling the invalid parameter handler by checking ourselves */ - if( s == NULL || n == 0 || fmt == NULL ) - return( -1 ); - - va_start( argp, fmt ); -#if defined(_TRUNCATE) - ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); -#else - ret = _vsnprintf( s, n, fmt, argp ); - if( ret < 0 || (size_t) ret == n ) - { - s[n-1] = '\0'; - ret = -1; - } -#endif - va_end( argp ); - - return( ret ); -} -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_snprintf_uninit( char * s, size_t n, - const char * format, ... ) -{ - ((void) s); - ((void) n); - ((void) format); - return( 0 ); -} - -#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit -#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ - -int (*mbedtls_snprintf)( char * s, size_t n, - const char * format, - ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; - -int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, - const char * format, - ... ) ) -{ - mbedtls_snprintf = snprintf_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ - -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_printf_uninit( const char *format, ... ) -{ - ((void) format); - return( 0 ); -} - -#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit -#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ - -int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; - -int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) -{ - mbedtls_printf = printf_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ - -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) -{ - ((void) stream); - ((void) format); - return( 0 ); -} - -#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit -#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ - -int (*mbedtls_fprintf)( FILE *, const char *, ... ) = - MBEDTLS_PLATFORM_STD_FPRINTF; - -int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) -{ - mbedtls_fprintf = fprintf_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ - -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_EXIT) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static void platform_exit_uninit( int status ) -{ - ((void) status); -} - -#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit -#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ - -void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; - -int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) -{ - mbedtls_exit = exit_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ - -#if defined(MBEDTLS_HAVE_TIME) - -#if defined(MBEDTLS_PLATFORM_TIME_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_TIME) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) -{ - ((void) timer); - return( 0 ); -} - -#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit -#endif /* !MBEDTLS_PLATFORM_STD_TIME */ - -mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; - -int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) -{ - mbedtls_time = time_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_TIME_ALT */ - -#endif /* MBEDTLS_HAVE_TIME */ - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) -/* Default implementations for the platform independent seed functions use - * standard libc file functions to read from and write to a pre-defined filename - */ -int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) -{ - FILE *file; - size_t n; -#error "fopen" - if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) - return -1; - - if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) - { - fclose( file ); - return -1; - } - - fclose( file ); - return( (int)n ); -} - -int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) -{ - FILE *file; - size_t n; - - if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) - return -1; - - if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) - { - fclose( file ); - return -1; - } - - fclose( file ); - return( (int)n ); -} -#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ - -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) -{ - ((void) buf); - ((void) buf_len); - return( -1 ); -} - -#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit -#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ - -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) -{ - ((void) buf); - ((void) buf_len); - return( -1 ); -} - -#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit -#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ - -int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = - MBEDTLS_PLATFORM_STD_NV_SEED_READ; -int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = - MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; - -int mbedtls_platform_set_nv_seed( - int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), - int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) -{ - mbedtls_nv_seed_read = nv_seed_read_func; - mbedtls_nv_seed_write = nv_seed_write_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#endif /* MBEDTLS_PLATFORM_C && !MBEDTLS_PLATFORM_ALT */ diff --git a/components/security/mbedtls/src/ripemd160.c b/components/security/mbedtls/src/ripemd160.c deleted file mode 100644 index cdb0a63c..00000000 --- a/components/security/mbedtls/src/ripemd160.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * RIPE MD-160 implementation - * - * 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) - */ - -/* - * The RIPEMD-160 algorithm was designed by RIPE in 1996 - * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html - * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_RIPEMD160_C) - -#include "mbedtls/ripemd160.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -/* 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; -} - -void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); -} - -void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); -} - -void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, - const mbedtls_ripemd160_context *src ) -{ - *dst = *src; -} - -/* - * RIPEMD-160 context setup - */ -void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) -/* - * Process one block - */ -void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned char data[64] ) -{ - uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; - - GET_UINT32_LE( X[ 0], data, 0 ); - GET_UINT32_LE( X[ 1], data, 4 ); - GET_UINT32_LE( X[ 2], data, 8 ); - GET_UINT32_LE( X[ 3], data, 12 ); - GET_UINT32_LE( X[ 4], data, 16 ); - GET_UINT32_LE( X[ 5], data, 20 ); - GET_UINT32_LE( X[ 6], data, 24 ); - GET_UINT32_LE( X[ 7], data, 28 ); - GET_UINT32_LE( X[ 8], data, 32 ); - GET_UINT32_LE( X[ 9], data, 36 ); - GET_UINT32_LE( X[10], data, 40 ); - GET_UINT32_LE( X[11], data, 44 ); - GET_UINT32_LE( X[12], data, 48 ); - GET_UINT32_LE( X[13], data, 52 ); - GET_UINT32_LE( X[14], data, 56 ); - GET_UINT32_LE( X[15], data, 60 ); - - A = Ap = ctx->state[0]; - B = Bp = ctx->state[1]; - C = Cp = ctx->state[2]; - D = Dp = ctx->state[3]; - E = Ep = ctx->state[4]; - -#define F1( x, y, z ) ( x ^ y ^ z ) -#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) ) -#define F3( x, y, z ) ( ( x | ~y ) ^ z ) -#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) ) -#define F5( x, y, z ) ( x ^ ( y | ~z ) ) - -#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) ) - -#define P( a, b, c, d, e, r, s, f, k ) \ - a += f( b, c, d ) + X[r] + k; \ - a = S( a, s ) + e; \ - c = S( c, 10 ); - -#define P2( a, b, c, d, e, r, s, rp, sp ) \ - P( a, b, c, d, e, r, s, F, K ); \ - P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp ); - -#define F F1 -#define K 0x00000000 -#define Fp F5 -#define Kp 0x50A28BE6 - P2( A, B, C, D, E, 0, 11, 5, 8 ); - P2( E, A, B, C, D, 1, 14, 14, 9 ); - P2( D, E, A, B, C, 2, 15, 7, 9 ); - P2( C, D, E, A, B, 3, 12, 0, 11 ); - P2( B, C, D, E, A, 4, 5, 9, 13 ); - P2( A, B, C, D, E, 5, 8, 2, 15 ); - P2( E, A, B, C, D, 6, 7, 11, 15 ); - P2( D, E, A, B, C, 7, 9, 4, 5 ); - P2( C, D, E, A, B, 8, 11, 13, 7 ); - P2( B, C, D, E, A, 9, 13, 6, 7 ); - P2( A, B, C, D, E, 10, 14, 15, 8 ); - P2( E, A, B, C, D, 11, 15, 8, 11 ); - P2( D, E, A, B, C, 12, 6, 1, 14 ); - P2( C, D, E, A, B, 13, 7, 10, 14 ); - P2( B, C, D, E, A, 14, 9, 3, 12 ); - P2( A, B, C, D, E, 15, 8, 12, 6 ); -#undef F -#undef K -#undef Fp -#undef Kp - -#define F F2 -#define K 0x5A827999 -#define Fp F4 -#define Kp 0x5C4DD124 - P2( E, A, B, C, D, 7, 7, 6, 9 ); - P2( D, E, A, B, C, 4, 6, 11, 13 ); - P2( C, D, E, A, B, 13, 8, 3, 15 ); - P2( B, C, D, E, A, 1, 13, 7, 7 ); - P2( A, B, C, D, E, 10, 11, 0, 12 ); - P2( E, A, B, C, D, 6, 9, 13, 8 ); - P2( D, E, A, B, C, 15, 7, 5, 9 ); - P2( C, D, E, A, B, 3, 15, 10, 11 ); - P2( B, C, D, E, A, 12, 7, 14, 7 ); - P2( A, B, C, D, E, 0, 12, 15, 7 ); - P2( E, A, B, C, D, 9, 15, 8, 12 ); - P2( D, E, A, B, C, 5, 9, 12, 7 ); - P2( C, D, E, A, B, 2, 11, 4, 6 ); - P2( B, C, D, E, A, 14, 7, 9, 15 ); - P2( A, B, C, D, E, 11, 13, 1, 13 ); - P2( E, A, B, C, D, 8, 12, 2, 11 ); -#undef F -#undef K -#undef Fp -#undef Kp - -#define F F3 -#define K 0x6ED9EBA1 -#define Fp F3 -#define Kp 0x6D703EF3 - P2( D, E, A, B, C, 3, 11, 15, 9 ); - P2( C, D, E, A, B, 10, 13, 5, 7 ); - P2( B, C, D, E, A, 14, 6, 1, 15 ); - P2( A, B, C, D, E, 4, 7, 3, 11 ); - P2( E, A, B, C, D, 9, 14, 7, 8 ); - P2( D, E, A, B, C, 15, 9, 14, 6 ); - P2( C, D, E, A, B, 8, 13, 6, 6 ); - P2( B, C, D, E, A, 1, 15, 9, 14 ); - P2( A, B, C, D, E, 2, 14, 11, 12 ); - P2( E, A, B, C, D, 7, 8, 8, 13 ); - P2( D, E, A, B, C, 0, 13, 12, 5 ); - P2( C, D, E, A, B, 6, 6, 2, 14 ); - P2( B, C, D, E, A, 13, 5, 10, 13 ); - P2( A, B, C, D, E, 11, 12, 0, 13 ); - P2( E, A, B, C, D, 5, 7, 4, 7 ); - P2( D, E, A, B, C, 12, 5, 13, 5 ); -#undef F -#undef K -#undef Fp -#undef Kp - -#define F F4 -#define K 0x8F1BBCDC -#define Fp F2 -#define Kp 0x7A6D76E9 - P2( C, D, E, A, B, 1, 11, 8, 15 ); - P2( B, C, D, E, A, 9, 12, 6, 5 ); - P2( A, B, C, D, E, 11, 14, 4, 8 ); - P2( E, A, B, C, D, 10, 15, 1, 11 ); - P2( D, E, A, B, C, 0, 14, 3, 14 ); - P2( C, D, E, A, B, 8, 15, 11, 14 ); - P2( B, C, D, E, A, 12, 9, 15, 6 ); - P2( A, B, C, D, E, 4, 8, 0, 14 ); - P2( E, A, B, C, D, 13, 9, 5, 6 ); - P2( D, E, A, B, C, 3, 14, 12, 9 ); - P2( C, D, E, A, B, 7, 5, 2, 12 ); - P2( B, C, D, E, A, 15, 6, 13, 9 ); - P2( A, B, C, D, E, 14, 8, 9, 12 ); - P2( E, A, B, C, D, 5, 6, 7, 5 ); - P2( D, E, A, B, C, 6, 5, 10, 15 ); - P2( C, D, E, A, B, 2, 12, 14, 8 ); -#undef F -#undef K -#undef Fp -#undef Kp - -#define F F5 -#define K 0xA953FD4E -#define Fp F1 -#define Kp 0x00000000 - P2( B, C, D, E, A, 4, 9, 12, 8 ); - P2( A, B, C, D, E, 0, 15, 15, 5 ); - P2( E, A, B, C, D, 5, 5, 10, 12 ); - P2( D, E, A, B, C, 9, 11, 4, 9 ); - P2( C, D, E, A, B, 7, 6, 1, 12 ); - P2( B, C, D, E, A, 12, 8, 5, 5 ); - P2( A, B, C, D, E, 2, 13, 8, 14 ); - P2( E, A, B, C, D, 10, 12, 7, 6 ); - P2( D, E, A, B, C, 14, 5, 6, 8 ); - P2( C, D, E, A, B, 1, 12, 2, 13 ); - P2( B, C, D, E, A, 3, 13, 13, 6 ); - P2( A, B, C, D, E, 8, 14, 14, 5 ); - P2( E, A, B, C, D, 11, 11, 0, 15 ); - P2( D, E, A, B, C, 6, 8, 3, 13 ); - P2( C, D, E, A, B, 15, 5, 9, 11 ); - P2( B, C, D, E, A, 13, 6, 11, 11 ); -#undef F -#undef K -#undef Fp -#undef Kp - - C = ctx->state[1] + C + Dp; - ctx->state[1] = ctx->state[2] + D + Ep; - ctx->state[2] = ctx->state[3] + E + Ap; - ctx->state[3] = ctx->state[4] + A + Bp; - ctx->state[4] = ctx->state[0] + B + Cp; - ctx->state[0] = C; -} -#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ - -/* - * RIPEMD-160 process buffer - */ -void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, - const unsigned char *input, size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_ripemd160_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_ripemd160_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), input, ilen ); - } -} - -static const unsigned char ripemd160_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * RIPEMD-160 final digest - */ -void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_ripemd160_update( ctx, ripemd160_padding, padn ); - mbedtls_ripemd160_update( ctx, msglen, 8 ); - - PUT_UINT32_LE( ctx->state[0], output, 0 ); - PUT_UINT32_LE( ctx->state[1], output, 4 ); - PUT_UINT32_LE( ctx->state[2], output, 8 ); - PUT_UINT32_LE( ctx->state[3], output, 12 ); - PUT_UINT32_LE( ctx->state[4], output, 16 ); -} - -/* - * output = RIPEMD-160( input buffer ) - */ -void mbedtls_ripemd160( const unsigned char *input, size_t ilen, - unsigned char output[20] ) -{ - mbedtls_ripemd160_context ctx; - - mbedtls_ripemd160_init( &ctx ); - mbedtls_ripemd160_starts( &ctx ); - mbedtls_ripemd160_update( &ctx, input, ilen ); - mbedtls_ripemd160_finish( &ctx, output ); - mbedtls_ripemd160_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) -/* - * Test vectors from the RIPEMD-160 paper and - * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC - */ -#define TESTS 8 -#define KEYS 2 -static const char *ripemd160_test_input[TESTS] = -{ - "", - "a", - "abc", - "message digest", - "abcdefghijklmnopqrstuvwxyz", - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", -}; - -static const unsigned char ripemd160_test_md[TESTS][20] = -{ - { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, - 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, - { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, - 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, - { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, - 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, - { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, - 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, - { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, - 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, - { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, - 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, - { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, - 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, - { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, - 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, -}; - -/* - * Checkup routine - */ -int mbedtls_ripemd160_self_test( int verbose ) -{ - int i; - unsigned char output[20]; - - memset( output, 0, sizeof output ); - - for( i = 0; i < TESTS; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); - - mbedtls_ripemd160( (const unsigned char *) ripemd160_test_input[i], - strlen( ripemd160_test_input[i] ), - output ); - - if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_RIPEMD160_C */ diff --git a/components/security/mbedtls/src/rsa.c b/components/security/mbedtls/src/rsa.c deleted file mode 100644 index 69af33c4..00000000 --- a/components/security/mbedtls/src/rsa.c +++ /dev/null @@ -1,1738 +0,0 @@ -/* - * The RSA public-key cryptosystem - * - * 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) - */ -/* - * The following sources were referenced in the design of this implementation - * of the RSA algorithm: - * - * [1] A method for obtaining digital signatures and public-key cryptosystems - * R Rivest, A Shamir, and L Adleman - * http://people.csail.mit.edu/rivest/pubs.html#RSA78 - * - * [2] Handbook of Applied Cryptography - 1997, Chapter 8 - * Menezes, van Oorschot and Vanstone - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if !defined(MBEDTLS_PK_ALT) - -#if defined(MBEDTLS_RSA_C) - -#include "mbedtls/rsa.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_PKCS1_V21) -#include "mbedtls/md.h" -#endif - -#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) -#include -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* - * Initialize an RSA context - */ -void mbedtls_rsa_init( mbedtls_rsa_context *ctx, - int padding, - int hash_id ) -{ - memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); - - mbedtls_rsa_set_padding( ctx, padding, hash_id ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -/* - * Set padding for an existing RSA context - */ -void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) -{ - ctx->padding = padding; - ctx->hash_id = hash_id; -} - -#if defined(MBEDTLS_GENPRIME) - -/* - * Generate an RSA keypair - */ -int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ) -{ - int ret; - mbedtls_mpi P1, Q1, H, G; - - if( f_rng == NULL || nbits < 128 || exponent < 3 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( nbits % 2 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); - mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); - - /* - * find primes P and Q with Q < P so that: - * GCD( E, (P-1)*(Q-1) ) == 1 - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); - - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, - f_rng, p_rng ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, - f_rng, p_rng ) ); - - if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) - continue; - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); - if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) - continue; - - if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) - mbedtls_mpi_swap( &ctx->P, &ctx->Q ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); - } - while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); - - /* - * D = E^-1 mod ((P-1)*(Q-1)) - * DP = D mod (P - 1) - * DQ = D mod (Q - 1) - * QP = Q^-1 mod P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); - - ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; - -cleanup: - - mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); - - if( ret != 0 ) - { - mbedtls_rsa_free( ctx ); - return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); - } - - return( 0 ); -} - -#endif /* MBEDTLS_GENPRIME */ - -/* - * Check a public RSA key - */ -int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) -{ - if( !ctx->N.p || !ctx->E.p ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - if( ( ctx->N.p[0] & 1 ) == 0 || - ( ctx->E.p[0] & 1 ) == 0 ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - if( mbedtls_mpi_bitlen( &ctx->N ) < 128 || - mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - if( mbedtls_mpi_bitlen( &ctx->E ) < 2 || - mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - return( 0 ); -} - -/* - * Check a private RSA key - */ -int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) -{ - int ret; - mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; - - if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 ) - return( ret ); - - if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); - mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); - mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ ); - mbedtls_mpi_init( &QP ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); - /* - * Check for a valid PKCS1v2 private key - */ - if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || - mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || - mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || - mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || - mbedtls_mpi_cmp_int( &L2, 0 ) != 0 || - mbedtls_mpi_cmp_int( &I, 1 ) != 0 || - mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; - } - -cleanup: - mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); - mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); - mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); - mbedtls_mpi_free( &QP ); - - if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) - return( ret ); - - if( ret != 0 ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret ); - - return( 0 ); -} - -/* - * Check if contexts holding a public and private key match - */ -int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ) -{ - if( mbedtls_rsa_check_pubkey( pub ) != 0 || - mbedtls_rsa_check_privkey( prv ) != 0 ) - { - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - } - - if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || - mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) - { - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - } - - return( 0 ); -} - -/* - * Do an RSA public key operation - */ -int mbedtls_rsa_public( mbedtls_rsa_context *ctx, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - size_t olen; - mbedtls_mpi T; - - mbedtls_mpi_init( &T ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); - - if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - goto cleanup; - } - - olen = ctx->len; - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); - -cleanup: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - mbedtls_mpi_free( &T ); - - if( ret != 0 ) - return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Generate or update blinding values, see section 10 of: - * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, - * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer - * Berlin Heidelberg, 1996. p. 104-113. - */ -static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret, count = 0; - - if( ctx->Vf.p != NULL ) - { - /* We already have blinding values, just update them by squaring */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); - - goto cleanup; - } - - /* Unblinding value: Vf = random number, invertible mod N */ - do { - if( count++ > 10 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); - } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); - - /* Blinding value: Vi = Vf^(-e) mod N */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); - - -cleanup: - return( ret ); -} - -/* - * Do an RSA private key operation - */ -int mbedtls_rsa_private( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - size_t olen; - mbedtls_mpi T, T1, T2; - - /* Make sure we have private key info, prevent possible misuse */ - if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); - if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - goto cleanup; - } - - if( f_rng != NULL ) - { - /* - * Blinding - * T = T * Vi mod N - */ - MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); - } - -#if defined(MBEDTLS_RSA_NO_CRT) - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); -#else - /* - * faster decryption using the CRT - * - * T1 = input ^ dP mod P - * T2 = input ^ dQ mod Q - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); - - /* - * T = (T1 - T2) * (Q^-1 mod P) mod P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); - - /* - * T = T2 + T * Q - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); -#endif /* MBEDTLS_RSA_NO_CRT */ - - if( f_rng != NULL ) - { - /* - * Unblind - * T = T * Vf mod N - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); - } - - olen = ctx->len; - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); - -cleanup: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); - - if( ret != 0 ) - return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); - - return( 0 ); -} - -#if defined(MBEDTLS_PKCS1_V21) -/** - * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. - * - * \param dst buffer to mask - * \param dlen length of destination buffer - * \param src source of the mask generation - * \param slen length of the source buffer - * \param md_ctx message digest context to use - */ -static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, - size_t slen, mbedtls_md_context_t *md_ctx ) -{ - unsigned char mask[MBEDTLS_MD_MAX_SIZE]; - unsigned char counter[4]; - unsigned char *p; - unsigned int hlen; - size_t i, use_len; - - memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); - memset( counter, 0, 4 ); - - hlen = mbedtls_md_get_size( md_ctx->md_info ); - - /* Generate and apply dbMask */ - p = dst; - - while( dlen > 0 ) - { - use_len = hlen; - if( dlen < hlen ) - use_len = dlen; - - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, src, slen ); - mbedtls_md_update( md_ctx, counter, 4 ); - mbedtls_md_finish( md_ctx, mask ); - - for( i = 0; i < use_len; ++i ) - *p++ ^= mask[i]; - - counter[3]++; - - dlen -= use_len; - } -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function - */ -int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - size_t olen; - int ret; - unsigned char *p = output; - unsigned int hlen; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( f_rng == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - hlen = mbedtls_md_get_size( md_info ); - - /* first comparison checks for overflow */ - if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - memset( output, 0, olen ); - - *p++ = 0; - - /* Generate a random octet string seed */ - if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); - - p += hlen; - - /* Construct DB */ - mbedtls_md( md_info, label, label_len, p ); - p += hlen; - p += olen - 2 * hlen - 2 - ilen; - *p++ = 1; - memcpy( p, input, ilen ); - - mbedtls_md_init( &md_ctx ); - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } - - /* maskedDB: Apply dbMask to DB */ - mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, - &md_ctx ); - - /* maskedSeed: Apply seedMask to seed */ - mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, - &md_ctx ); - - mbedtls_md_free( &md_ctx ); - - return( ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, output, output ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V15) -/* - * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function - */ -int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - size_t nb_pad, olen; - int ret; - unsigned char *p = output; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - // We don't check p_rng because it won't be dereferenced here - if( f_rng == NULL || input == NULL || output == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - - /* first comparison checks for overflow */ - if( ilen + 11 < ilen || olen < ilen + 11 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - nb_pad = olen - 3 - ilen; - - *p++ = 0; - if( mode == MBEDTLS_RSA_PUBLIC ) - { - *p++ = MBEDTLS_RSA_CRYPT; - - while( nb_pad-- > 0 ) - { - int rng_dl = 100; - - do { - ret = f_rng( p_rng, p, 1 ); - } while( *p == 0 && --rng_dl && ret == 0 ); - - /* Check if RNG failed to generate data */ - if( rng_dl == 0 || ret != 0 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); - - p++; - } - } - else - { - *p++ = MBEDTLS_RSA_SIGN; - - while( nb_pad-- > 0 ) - *p++ = 0xFF; - } - - *p++ = 0; - memcpy( p, input, ilen ); - - return( ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, output, output ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Add the message padding, then do an RSA operation - */ -int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - switch( ctx->padding ) - { -#if defined(MBEDTLS_PKCS1_V15) - case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, - input, output ); -#endif - -#if defined(MBEDTLS_PKCS1_V21) - case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, - ilen, input, output ); -#endif - - default: - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(MBEDTLS_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function - */ -int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ) -{ - int ret; - size_t ilen, i, pad_len; - unsigned char *p, bad, pad_done; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; - unsigned int hlen; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - /* - * Parameters sanity checks - */ - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ilen = ctx->len; - - if( ilen < 16 || ilen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hlen = mbedtls_md_get_size( md_info ); - - // checking for integer underflow - if( 2 * hlen + 2 > ilen ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - /* - * RSA operation - */ - ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, input, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); - - if( ret != 0 ) - return( ret ); - - /* - * Unmask data and generate lHash - */ - mbedtls_md_init( &md_ctx ); - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } - - - /* Generate lHash */ - mbedtls_md( md_info, label, label_len, lhash ); - - /* seed: Apply seedMask to maskedSeed */ - mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, - &md_ctx ); - - /* DB: Apply dbMask to maskedDB */ - mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, - &md_ctx ); - - mbedtls_md_free( &md_ctx ); - - /* - * Check contents, in "constant-time" - */ - p = buf; - bad = 0; - - bad |= *p++; /* First byte must be 0 */ - - p += hlen; /* Skip seed */ - - /* Check lHash */ - for( i = 0; i < hlen; i++ ) - bad |= lhash[i] ^ *p++; - - /* Get zero-padding len, but always read till end of buffer - * (minus one, for the 01 byte) */ - pad_len = 0; - pad_done = 0; - for( i = 0; i < ilen - 2 * hlen - 2; i++ ) - { - pad_done |= p[i]; - pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; - } - - p += pad_len; - bad |= *p++ ^ 0x01; - - /* - * The only information "leaked" is whether the padding was correct or not - * (eg, no data is copied if it was not correct). This meets the - * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between - * the different error conditions. - */ - if( bad != 0 ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - - if( ilen - ( p - buf ) > output_max_len ) - return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); - - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); - - return( 0 ); -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V15) -/* - * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function - */ -int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - int ret; - size_t ilen, pad_count = 0, i; - unsigned char *p, bad, pad_done = 0; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ilen = ctx->len; - - if( ilen < 16 || ilen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, input, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - bad = 0; - - /* - * Check and get padding len in "constant-time" - */ - bad |= *p++; /* First byte must be 0 */ - - /* This test does not depend on secret data */ - if( mode == MBEDTLS_RSA_PRIVATE ) - { - bad |= *p++ ^ MBEDTLS_RSA_CRYPT; - - /* Get padding len, but always read till end of buffer - * (minus one, for the 00 byte) */ - for( i = 0; i < ilen - 3; i++ ) - { - pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; - pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; - } - - p += pad_count; - bad |= *p++; /* Must be zero */ - } - else - { - bad |= *p++ ^ MBEDTLS_RSA_SIGN; - - /* Get padding len, but always read till end of buffer - * (minus one, for the 00 byte) */ - for( i = 0; i < ilen - 3; i++ ) - { - pad_done |= ( p[i] != 0xFF ); - pad_count += ( pad_done == 0 ); - } - - p += pad_count; - bad |= *p++; /* Must be zero */ - } - - bad |= ( pad_count < 8 ); - - if( bad ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - - if( ilen - ( p - buf ) > output_max_len ) - return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); - - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); - - return( 0 ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Do an RSA operation, then remove the message padding - */ -int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - switch( ctx->padding ) - { -#if defined(MBEDTLS_PKCS1_V15) - case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, - input, output, output_max_len ); -#endif - -#if defined(MBEDTLS_PKCS1_V21) - case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, - olen, input, output, - output_max_len ); -#endif - - default: - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(MBEDTLS_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function - */ -int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t olen; - unsigned char *p = sig; - unsigned char salt[MBEDTLS_MD_MAX_SIZE]; - unsigned int slen, hlen, offset = 0; - int ret; - size_t msb; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( f_rng == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - - if( md_alg != MBEDTLS_MD_NONE ) - { - /* Gather length of hash to sign */ - md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hashlen = mbedtls_md_get_size( md_info ); - } - - md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hlen = mbedtls_md_get_size( md_info ); - slen = hlen; - - if( olen < hlen + slen + 2 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - memset( sig, 0, olen ); - - /* Generate salt of length slen */ - if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); - - /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ - msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; - p += olen - hlen * 2 - 2; - *p++ = 0x01; - memcpy( p, salt, slen ); - p += slen; - - mbedtls_md_init( &md_ctx ); - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } - - /* Generate H = Hash( M' ) */ - mbedtls_md_starts( &md_ctx ); - mbedtls_md_update( &md_ctx, p, 8 ); - mbedtls_md_update( &md_ctx, hash, hashlen ); - mbedtls_md_update( &md_ctx, salt, slen ); - mbedtls_md_finish( &md_ctx, p ); - - /* Compensate for boundary condition when applying mask */ - if( msb % 8 == 0 ) - offset = 1; - - /* maskedDB: Apply dbMask to DB */ - mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); - - mbedtls_md_free( &md_ctx ); - - msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; - sig[0] &= 0xFF >> ( olen * 8 - msb ); - - p += hlen; - *p++ = 0xBC; - - return( ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, sig, sig ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V15) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function - */ -/* - * Do an RSA operation to sign the message digest - */ -int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t nb_pad, olen, oid_size = 0; - unsigned char *p = sig; - const char *oid = NULL; - unsigned char *sig_try = NULL, *verif = NULL; - size_t i; - unsigned char diff; - volatile unsigned char diff_no_optimize; - int ret; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - nb_pad = olen - 3; - - if( md_alg != MBEDTLS_MD_NONE ) - { - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - nb_pad -= 10 + oid_size; - - hashlen = mbedtls_md_get_size( md_info ); - } - - nb_pad -= hashlen; - - if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - *p++ = 0; - *p++ = MBEDTLS_RSA_SIGN; - memset( p, 0xFF, nb_pad ); - p += nb_pad; - *p++ = 0; - - if( md_alg == MBEDTLS_MD_NONE ) - { - memcpy( p, hash, hashlen ); - } - else - { - /* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x04 + oid_size ); - *p++ = MBEDTLS_ASN1_OID; - *p++ = oid_size & 0xFF; - memcpy( p, oid, oid_size ); - p += oid_size; - *p++ = MBEDTLS_ASN1_NULL; - *p++ = 0x00; - *p++ = MBEDTLS_ASN1_OCTET_STRING; - *p++ = hashlen; - memcpy( p, hash, hashlen ); - } - - if( mode == MBEDTLS_RSA_PUBLIC ) - return( mbedtls_rsa_public( ctx, sig, sig ) ); - - /* - * In order to prevent Lenstra's attack, make the signature in a - * temporary buffer and check it before returning it. - */ - sig_try = mbedtls_calloc( 1, ctx->len ); - if( sig_try == NULL ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - verif = mbedtls_calloc( 1, ctx->len ); - if( verif == NULL ) - { - mbedtls_free( sig_try ); - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - } - - MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); - MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); - - /* Compare in constant time just in case */ - for( diff = 0, i = 0; i < ctx->len; i++ ) - diff |= verif[i] ^ sig[i]; - diff_no_optimize = diff; - - if( diff_no_optimize != 0 ) - { - ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; - goto cleanup; - } - - memcpy( sig, sig_try, ctx->len ); - -cleanup: - mbedtls_free( sig_try ); - mbedtls_free( verif ); - - return( ret ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Do an RSA operation to sign the message digest - */ -int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - switch( ctx->padding ) - { -#if defined(MBEDTLS_PKCS1_V15) - case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig ); -#endif - -#if defined(MBEDTLS_PKCS1_V21) - case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig ); -#endif - - default: - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(MBEDTLS_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function - */ -int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - mbedtls_md_type_t mgf1_hash_id, - int expected_salt_len, - const unsigned char *sig ) -{ - int ret; - size_t siglen; - unsigned char *p; - unsigned char result[MBEDTLS_MD_MAX_SIZE]; - unsigned char zeros[8]; - unsigned int hlen; - size_t slen, msb; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - siglen = ctx->len; - - if( siglen < 16 || siglen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, sig, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - if( buf[siglen - 1] != 0xBC ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - - if( md_alg != MBEDTLS_MD_NONE ) - { - /* Gather length of hash to sign */ - md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hashlen = mbedtls_md_get_size( md_info ); - } - - md_info = mbedtls_md_info_from_type( mgf1_hash_id ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hlen = mbedtls_md_get_size( md_info ); - slen = siglen - hlen - 1; /* Currently length of salt + padding */ - - memset( zeros, 0, 8 ); - - /* - * Note: EMSA-PSS verification is over the length of N - 1 bits - */ - msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; - - /* Compensate for boundary condition when applying mask */ - if( msb % 8 == 0 ) - { - p++; - siglen -= 1; - } - if( buf[0] >> ( 8 - siglen * 8 + msb ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - mbedtls_md_init( &md_ctx ); - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } - - mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); - - buf[0] &= 0xFF >> ( siglen * 8 - msb ); - - while( p < buf + siglen && *p == 0 ) - p++; - - if( p == buf + siglen || - *p++ != 0x01 ) - { - mbedtls_md_free( &md_ctx ); - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } - - /* Actual salt len */ - slen -= p - buf; - - if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && - slen != (size_t) expected_salt_len ) - { - mbedtls_md_free( &md_ctx ); - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } - - /* - * Generate H = Hash( M' ) - */ - mbedtls_md_starts( &md_ctx ); - mbedtls_md_update( &md_ctx, zeros, 8 ); - mbedtls_md_update( &md_ctx, hash, hashlen ); - mbedtls_md_update( &md_ctx, p, slen ); - mbedtls_md_finish( &md_ctx, result ); - - mbedtls_md_free( &md_ctx ); - - if( memcmp( p + slen, result, hlen ) == 0 ) - return( 0 ); - else - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); -} - -/* - * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function - */ -int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ) -{ - mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) - ? (mbedtls_md_type_t) ctx->hash_id - : md_alg; - - return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, - md_alg, hashlen, hash, - mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, - sig ) ); - -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V15) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function - */ -int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ) -{ - int ret; - size_t len, siglen, asn1_len; - unsigned char *p, *end; -#if !defined(MBEDTLS_IOT_SPECIFIC) - mbedtls_md_type_t msg_md_alg; -#endif - const mbedtls_md_info_t *md_info; - mbedtls_asn1_buf oid; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - siglen = ctx->len; - - if( siglen < 16 || siglen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, sig, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - if( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - - while( *p != 0 ) - { - if( p >= buf + siglen - 1 || *p != 0xFF ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - p++; - } - p++; - - len = siglen - ( p - buf ); - - if( len == hashlen && md_alg == MBEDTLS_MD_NONE ) - { - if( memcmp( p, hash, hashlen ) == 0 ) - return( 0 ); - else - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - } - - md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - hashlen = mbedtls_md_get_size( md_info ); - - end = p + len; - - /* - * Parse the ASN.1 structure inside the PKCS#1 v1.5 structure - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( asn1_len + 2 != len ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( asn1_len + 6 + hashlen != len ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - oid.p = p; - p += oid.len; - -#if !defined(MBEDTLS_IOT_SPECIFIC) - if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( md_alg != msg_md_alg ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); -#endif - - /* - * assume the algorithm parameters must be NULL - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( asn1_len != hashlen ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( memcmp( p, hash, hashlen ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - p += hashlen; - - if( p != end ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - return( 0 ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Do an RSA operation and check the message digest - */ -int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ) -{ - switch( ctx->padding ) - { -#if defined(MBEDTLS_PKCS1_V15) - case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig ); -#endif - -#if defined(MBEDTLS_PKCS1_V21) - case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig ); -#endif - - default: - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } -} - -/* - * Copy the components of an RSA key - */ -int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) -{ - int ret; - - dst->ver = src->ver; - dst->len = src->len; - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); - - dst->padding = src->padding; - dst->hash_id = src->hash_id; - -cleanup: - if( ret != 0 ) - mbedtls_rsa_free( dst ); - - return( ret ); -} - -/* - * Free the components of an RSA key - */ -void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) -{ - mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN ); - mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); - mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D ); - mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif -} - -#if defined(MBEDTLS_SELF_TEST) - -#include "mbedtls/sha1.h" - -/* - * Example RSA-1024 keypair, for test purposes - */ -#define KEY_LEN 128 - -#define RSA_N "9292758453063D803DD603D5E777D788" \ - "8ED1D5BF35786190FA2F23EBC0848AEA" \ - "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ - "7130B9CED7ACDF54CFC7555AC14EEBAB" \ - "93A89813FBF3C4F8066D2D800F7C38A8" \ - "1AE31942917403FF4946B0A83D3D3E05" \ - "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ - "5E94BB77B07507233A0BC7BAC8F90F79" - -#define RSA_E "10001" - -#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ - "66CA472BC44D253102F8B4A9D3BFA750" \ - "91386C0077937FE33FA3252D28855837" \ - "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ - "DF79C5CE07EE72C7F123142198164234" \ - "CABB724CF78B8173B9F880FC86322407" \ - "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ - "071513A1E85B5DFA031F21ECAE91A34D" - -#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ - "2C01CAD19EA484A87EA4377637E75500" \ - "FCB2005C5C7DD6EC4AC023CDA285D796" \ - "C3D9E75E1EFC42488BB4F1D13AC30A57" - -#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ - "E211C2B9E5DB1ED0BF61D0D9899620F4" \ - "910E4168387E3C30AA1E00C339A79508" \ - "8452DD96A9A5EA5D9DCA68DA636032AF" - -#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ - "3C94D22288ACD763FD8E5600ED4A702D" \ - "F84198A5F06C2E72236AE490C93F07F8" \ - "3CC559CD27BC2D1CA488811730BB5725" - -#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ - "D8AAEA56749EA28623272E4F7D0592AF" \ - "7C1F1313CAC9471B5C523BFE592F517B" \ - "407A1BD76C164B93DA2D32A383E58357" - -#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ - "F38D18D2B2F0E2DD275AA977E2BF4411" \ - "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ - "A74206CEC169D74BF5A8C50D6F48EA08" - -#define PT_LEN 24 -#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ - "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" - -#if defined(MBEDTLS_PKCS1_V15) -static int myrand( void *rng_state, unsigned char *output, size_t len ) -{ -#if !defined(__OpenBSD__) - size_t i; - - if( rng_state != NULL ) - rng_state = NULL; - - for( i = 0; i < len; ++i ) - output[i] = rand(); -#else - if( rng_state != NULL ) - rng_state = NULL; - - arc4random_buf( output, len ); -#endif /* !OpenBSD */ - - return( 0 ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Checkup routine - */ -int mbedtls_rsa_self_test( int verbose ) -{ - int ret = 0; -#if defined(MBEDTLS_PKCS1_V15) - size_t len; - mbedtls_rsa_context rsa; - unsigned char rsa_plaintext[PT_LEN]; - unsigned char rsa_decrypted[PT_LEN]; - unsigned char rsa_ciphertext[KEY_LEN]; -#if defined(MBEDTLS_SHA1_C) - unsigned char sha1sum[20]; -#endif - - mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); - - rsa.len = KEY_LEN; - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) ); - - if( verbose != 0 ) - mbedtls_printf( " RSA key validation: " ); - - if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || - mbedtls_rsa_check_privkey( &rsa ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n PKCS#1 encryption : " ); - - memcpy( rsa_plaintext, RSA_PT, PT_LEN ); - - if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN, - rsa_plaintext, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n PKCS#1 decryption : " ); - - if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len, - rsa_ciphertext, rsa_decrypted, - sizeof(rsa_decrypted) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -#if defined(MBEDTLS_SHA1_C) - if( verbose != 0 ) - mbedtls_printf( " PKCS#1 data sign : " ); - - mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ); - - if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); - - if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); -#endif /* MBEDTLS_SHA1_C */ - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -cleanup: - mbedtls_rsa_free( &rsa ); -#else /* MBEDTLS_PKCS1_V15 */ - ((void) verbose); -#endif /* MBEDTLS_PKCS1_V15 */ - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_RSA_C */ - -#endif /* MBEDTLS_PK_ALT */ diff --git a/components/security/mbedtls/src/sha1.c b/components/security/mbedtls/src/sha1.c deleted file mode 100644 index 7380fb39..00000000 --- a/components/security/mbedtls/src/sha1.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * FIPS-180-1 compliant SHA-1 implementation - * - * 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) - */ -/* - * The SHA-1 standard was published by NIST in 1993. - * - * http://www.itl.nist.gov/fipspubs/fip180-1.htm - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SHA1_C) - -#include "mbedtls/sha1.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_SHA1_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); -} - -void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); -} - -void mbedtls_sha1_clone( mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src ) -{ - *dst = *src; -} - -/* - * SHA-1 context setup - */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -#if !defined(MBEDTLS_SHA1_PROCESS_ALT) -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) -{ - uint32_t temp, W[16], A, B, C, D, E; - - GET_UINT32_BE( W[ 0], data, 0 ); - GET_UINT32_BE( W[ 1], data, 4 ); - GET_UINT32_BE( W[ 2], data, 8 ); - GET_UINT32_BE( W[ 3], data, 12 ); - GET_UINT32_BE( W[ 4], data, 16 ); - GET_UINT32_BE( W[ 5], data, 20 ); - GET_UINT32_BE( W[ 6], data, 24 ); - GET_UINT32_BE( W[ 7], data, 28 ); - GET_UINT32_BE( W[ 8], data, 32 ); - GET_UINT32_BE( W[ 9], data, 36 ); - GET_UINT32_BE( W[10], data, 40 ); - GET_UINT32_BE( W[11], data, 44 ); - GET_UINT32_BE( W[12], data, 48 ); - GET_UINT32_BE( W[13], data, 52 ); - GET_UINT32_BE( W[14], data, 56 ); - GET_UINT32_BE( W[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define R(t) \ -( \ - temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ - W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ - ( W[t & 0x0F] = S(temp,1) ) \ -) - -#define P(a,b,c,d,e,x) \ -{ \ - e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define K 0x5A827999 - - P( A, B, C, D, E, W[0] ); - P( E, A, B, C, D, W[1] ); - P( D, E, A, B, C, W[2] ); - P( C, D, E, A, B, W[3] ); - P( B, C, D, E, A, W[4] ); - P( A, B, C, D, E, W[5] ); - P( E, A, B, C, D, W[6] ); - P( D, E, A, B, C, W[7] ); - P( C, D, E, A, B, W[8] ); - P( B, C, D, E, A, W[9] ); - P( A, B, C, D, E, W[10] ); - P( E, A, B, C, D, W[11] ); - P( D, E, A, B, C, W[12] ); - P( C, D, E, A, B, W[13] ); - P( B, C, D, E, A, W[14] ); - P( A, B, C, D, E, W[15] ); - P( E, A, B, C, D, R(16) ); - P( D, E, A, B, C, R(17) ); - P( C, D, E, A, B, R(18) ); - P( B, C, D, E, A, R(19) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0x6ED9EBA1 - - P( A, B, C, D, E, R(20) ); - P( E, A, B, C, D, R(21) ); - P( D, E, A, B, C, R(22) ); - P( C, D, E, A, B, R(23) ); - P( B, C, D, E, A, R(24) ); - P( A, B, C, D, E, R(25) ); - P( E, A, B, C, D, R(26) ); - P( D, E, A, B, C, R(27) ); - P( C, D, E, A, B, R(28) ); - P( B, C, D, E, A, R(29) ); - P( A, B, C, D, E, R(30) ); - P( E, A, B, C, D, R(31) ); - P( D, E, A, B, C, R(32) ); - P( C, D, E, A, B, R(33) ); - P( B, C, D, E, A, R(34) ); - P( A, B, C, D, E, R(35) ); - P( E, A, B, C, D, R(36) ); - P( D, E, A, B, C, R(37) ); - P( C, D, E, A, B, R(38) ); - P( B, C, D, E, A, R(39) ); - -#undef K -#undef F - -#define F(x,y,z) ((x & y) | (z & (x | y))) -#define K 0x8F1BBCDC - - P( A, B, C, D, E, R(40) ); - P( E, A, B, C, D, R(41) ); - P( D, E, A, B, C, R(42) ); - P( C, D, E, A, B, R(43) ); - P( B, C, D, E, A, R(44) ); - P( A, B, C, D, E, R(45) ); - P( E, A, B, C, D, R(46) ); - P( D, E, A, B, C, R(47) ); - P( C, D, E, A, B, R(48) ); - P( B, C, D, E, A, R(49) ); - P( A, B, C, D, E, R(50) ); - P( E, A, B, C, D, R(51) ); - P( D, E, A, B, C, R(52) ); - P( C, D, E, A, B, R(53) ); - P( B, C, D, E, A, R(54) ); - P( A, B, C, D, E, R(55) ); - P( E, A, B, C, D, R(56) ); - P( D, E, A, B, C, R(57) ); - P( C, D, E, A, B, R(58) ); - P( B, C, D, E, A, R(59) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0xCA62C1D6 - - P( A, B, C, D, E, R(60) ); - P( E, A, B, C, D, R(61) ); - P( D, E, A, B, C, R(62) ); - P( C, D, E, A, B, R(63) ); - P( B, C, D, E, A, R(64) ); - P( A, B, C, D, E, R(65) ); - P( E, A, B, C, D, R(66) ); - P( D, E, A, B, C, R(67) ); - P( C, D, E, A, B, R(68) ); - P( B, C, D, E, A, R(69) ); - P( A, B, C, D, E, R(70) ); - P( E, A, B, C, D, R(71) ); - P( D, E, A, B, C, R(72) ); - P( C, D, E, A, B, R(73) ); - P( B, C, D, E, A, R(74) ); - P( A, B, C, D, E, R(75) ); - P( E, A, B, C, D, R(76) ); - P( D, E, A, B, C, R(77) ); - P( C, D, E, A, B, R(78) ); - P( B, C, D, E, A, R(79) ); - -#undef K -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; -} -#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ - -/* - * SHA-1 process buffer - */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha1_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_sha1_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - memcpy( (void *) (ctx->buffer + left), input, ilen ); -} - -static const unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-1 final digest - */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_sha1_update( ctx, sha1_padding, padn ); - mbedtls_sha1_update( ctx, msglen, 8 ); - - PUT_UINT32_BE( ctx->state[0], output, 0 ); - PUT_UINT32_BE( ctx->state[1], output, 4 ); - PUT_UINT32_BE( ctx->state[2], output, 8 ); - PUT_UINT32_BE( ctx->state[3], output, 12 ); - PUT_UINT32_BE( ctx->state[4], output, 16 ); -} - - -/* - * output = SHA-1( input buffer ) - */ -void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) -{ - mbedtls_sha1_context ctx; - - mbedtls_sha1_init( &ctx ); - mbedtls_sha1_starts( &ctx ); - mbedtls_sha1_update( &ctx, input, ilen ); - mbedtls_sha1_finish( &ctx, output ); - mbedtls_sha1_free( &ctx ); -} - -#endif /* !MBEDTLS_SHA1_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * FIPS-180-1 test vectors - */ -static const unsigned char sha1_test_buf[3][57] = -{ - { "abc" }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, - { "" } -}; - -static const int sha1_test_buflen[3] = -{ - 3, 56, 1000 -}; - -static const unsigned char sha1_test_sum[3][20] = -{ - { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, - 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, - { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, - 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, - { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, - 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } -}; - -/* - * Checkup routine - */ -int mbedtls_sha1_self_test( int verbose ) -{ - int i, j, buflen, ret = 0; - unsigned char buf[1024]; - unsigned char sha1sum[20]; - mbedtls_sha1_context ctx; - - mbedtls_sha1_init( &ctx ); - - /* - * SHA-1 - */ - for( i = 0; i < 3; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); - - mbedtls_sha1_starts( &ctx ); - - if( i == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - mbedtls_sha1_update( &ctx, buf, buflen ); - } - else - mbedtls_sha1_update( &ctx, sha1_test_buf[i], - sha1_test_buflen[i] ); - - mbedtls_sha1_finish( &ctx, sha1sum ); - - if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_sha1_free( &ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_SHA1_C */ diff --git a/components/security/mbedtls/src/sha256.c b/components/security/mbedtls/src/sha256.c deleted file mode 100644 index 8ad47c7e..00000000 --- a/components/security/mbedtls/src/sha256.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * FIPS-180-2 compliant SHA-256 implementation - * - * 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) - */ -/* - * The SHA-256 Secure Hash Standard was published by NIST in 2002. - * - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SHA256_C) - -#include "mbedtls/sha256.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_SHA256_ALT) - -/* 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; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -do { \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} while( 0 ) -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -do { \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} while( 0 ) -#endif - -void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); -} - -void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); -} - -void mbedtls_sha256_clone( mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src ) -{ - *dst = *src; -} - -/* - * SHA-256 context setup - */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - if( is224 == 0 ) - { - /* SHA-256 */ - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; - } - else - { - /* SHA-224 */ - ctx->state[0] = 0xC1059ED8; - ctx->state[1] = 0x367CD507; - ctx->state[2] = 0x3070DD17; - ctx->state[3] = 0xF70E5939; - ctx->state[4] = 0xFFC00B31; - ctx->state[5] = 0x68581511; - ctx->state[6] = 0x64F98FA7; - ctx->state[7] = 0xBEFA4FA4; - } - - ctx->is224 = is224; -} - -#if !defined(MBEDTLS_SHA256_PROCESS_ALT) -static const uint32_t K[] = -{ - 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, - 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, - 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, - 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, - 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, - 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, - 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, - 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, -}; - -#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) - -#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) - -#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define R(t) \ -( \ - W[t] = S1(W[t - 2]) + W[t - 7] + \ - S0(W[t - 15]) + W[t - 16] \ -) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) -{ - uint32_t temp1, temp2, W[64]; - uint32_t A[8]; - unsigned int i; - - for( i = 0; i < 8; i++ ) - A[i] = ctx->state[i]; - -#if defined(MBEDTLS_SHA256_SMALLER) - for( i = 0; i < 64; i++ ) - { - if( i < 16 ) - GET_UINT32_BE( W[i], data, 4 * i ); - else - R( i ); - - P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); - - temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; - A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; - } -#else /* MBEDTLS_SHA256_SMALLER */ - for( i = 0; i < 16; i++ ) - GET_UINT32_BE( W[i], data, 4 * i ); - - for( i = 0; i < 16; i += 8 ) - { - P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); - P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); - P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); - P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); - P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); - P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); - P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); - P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); - } - - for( i = 16; i < 64; i += 8 ) - { - P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); - P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); - P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); - P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); - P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); - P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); - P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); - P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); - } -#endif /* MBEDTLS_SHA256_SMALLER */ - - for( i = 0; i < 8; i++ ) - ctx->state[i] += A[i]; -} -#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ - -/* - * SHA-256 process buffer - */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha256_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_sha256_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - memcpy( (void *) (ctx->buffer + left), input, ilen ); -} - -static const unsigned char sha256_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-256 final digest - */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_sha256_update( ctx, sha256_padding, padn ); - mbedtls_sha256_update( ctx, msglen, 8 ); - - PUT_UINT32_BE( ctx->state[0], output, 0 ); - PUT_UINT32_BE( ctx->state[1], output, 4 ); - PUT_UINT32_BE( ctx->state[2], output, 8 ); - PUT_UINT32_BE( ctx->state[3], output, 12 ); - PUT_UINT32_BE( ctx->state[4], output, 16 ); - PUT_UINT32_BE( ctx->state[5], output, 20 ); - PUT_UINT32_BE( ctx->state[6], output, 24 ); - - if( ctx->is224 == 0 ) - PUT_UINT32_BE( ctx->state[7], output, 28 ); -} - - -/* - * output = SHA-256( input buffer ) - */ -void mbedtls_sha256( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ) -{ - mbedtls_sha256_context ctx; - - mbedtls_sha256_init( &ctx ); - mbedtls_sha256_starts( &ctx, is224 ); - mbedtls_sha256_update( &ctx, input, ilen ); - mbedtls_sha256_finish( &ctx, output ); - mbedtls_sha256_free( &ctx ); -} - -#endif /* !MBEDTLS_SHA256_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * FIPS-180-2 test vectors - */ -static const unsigned char sha256_test_buf[3][57] = -{ - { "abc" }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, - { "" } -}; - -static const int sha256_test_buflen[3] = -{ - 3, 56, 1000 -}; - -static const unsigned char sha256_test_sum[6][32] = -{ - /* - * SHA-224 test vectors - */ - { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, - 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, - 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, - 0xE3, 0x6C, 0x9D, 0xA7 }, - { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, - 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, - 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, - 0x52, 0x52, 0x25, 0x25 }, - { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, - 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, - 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, - 0x4E, 0xE7, 0xAD, 0x67 }, - - /* - * SHA-256 test vectors - */ - { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, - 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, - 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, - 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, - { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, - 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, - 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, - 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, - { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, - 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, - 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, - 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } -}; - -/* - * Checkup routine - */ -int mbedtls_sha256_self_test( int verbose ) -{ - int i, j, k, buflen, ret = 0; - unsigned char *buf; - unsigned char sha256sum[32]; - mbedtls_sha256_context ctx; - - buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); - if( NULL == buf ) - { - if( verbose != 0 ) - mbedtls_printf( "Buffer allocation failed\n" ); - - return( 1 ); - } - - mbedtls_sha256_init( &ctx ); - - for( i = 0; i < 6; i++ ) - { - j = i % 3; - k = i < 3; - - if( verbose != 0 ) - mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); - - mbedtls_sha256_starts( &ctx, k ); - - if( j == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - mbedtls_sha256_update( &ctx, buf, buflen ); - } - else - mbedtls_sha256_update( &ctx, sha256_test_buf[j], - sha256_test_buflen[j] ); - - mbedtls_sha256_finish( &ctx, sha256sum ); - - if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_sha256_free( &ctx ); - mbedtls_free( buf ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_SHA256_C */ diff --git a/components/security/mbedtls/src/sha512.c b/components/security/mbedtls/src/sha512.c deleted file mode 100644 index 724522ac..00000000 --- a/components/security/mbedtls/src/sha512.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - * FIPS-180-2 compliant SHA-384/512 implementation - * - * 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) - */ -/* - * The SHA-512 Secure Hash Standard was published by NIST in 2002. - * - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SHA512_C) - -#include "mbedtls/sha512.h" - -#if defined(_MSC_VER) || defined(__WATCOMC__) - #define UL64(x) x##ui64 -#else - #define UL64(x) x##ULL -#endif - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_SHA512_ALT) - -/* 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; -} - -/* - * 64-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT64_BE -#define GET_UINT64_BE(n,b,i) \ -{ \ - (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ - | ( (uint64_t) (b)[(i) + 1] << 48 ) \ - | ( (uint64_t) (b)[(i) + 2] << 40 ) \ - | ( (uint64_t) (b)[(i) + 3] << 32 ) \ - | ( (uint64_t) (b)[(i) + 4] << 24 ) \ - | ( (uint64_t) (b)[(i) + 5] << 16 ) \ - | ( (uint64_t) (b)[(i) + 6] << 8 ) \ - | ( (uint64_t) (b)[(i) + 7] ); \ -} -#endif /* GET_UINT64_BE */ - -#ifndef PUT_UINT64_BE -#define PUT_UINT64_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ - (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 7] = (unsigned char) ( (n) ); \ -} -#endif /* PUT_UINT64_BE */ - -void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); -} - -void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); -} - -void mbedtls_sha512_clone( mbedtls_sha512_context *dst, - const mbedtls_sha512_context *src ) -{ - *dst = *src; -} - -/* - * SHA-512 context setup - */ -void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - if( is384 == 0 ) - { - /* SHA-512 */ - ctx->state[0] = UL64(0x6A09E667F3BCC908); - ctx->state[1] = UL64(0xBB67AE8584CAA73B); - ctx->state[2] = UL64(0x3C6EF372FE94F82B); - ctx->state[3] = UL64(0xA54FF53A5F1D36F1); - ctx->state[4] = UL64(0x510E527FADE682D1); - ctx->state[5] = UL64(0x9B05688C2B3E6C1F); - ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); - ctx->state[7] = UL64(0x5BE0CD19137E2179); - } - else - { - /* SHA-384 */ - ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); - ctx->state[1] = UL64(0x629A292A367CD507); - ctx->state[2] = UL64(0x9159015A3070DD17); - ctx->state[3] = UL64(0x152FECD8F70E5939); - ctx->state[4] = UL64(0x67332667FFC00B31); - ctx->state[5] = UL64(0x8EB44A8768581511); - ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); - ctx->state[7] = UL64(0x47B5481DBEFA4FA4); - } - - ctx->is384 = is384; -} - -#if !defined(MBEDTLS_SHA512_PROCESS_ALT) - -/* - * Round constants - */ -static const uint64_t K[80] = -{ - UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), - UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), - UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), - UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), - UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), - UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), - UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), - UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), - UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), - UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), - UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), - UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), - UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), - UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), - UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), - UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), - UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), - UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), - UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), - UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), - UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), - UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), - UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), - UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), - UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), - UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), - UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), - UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), - UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), - UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), - UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), - UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), - UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), - UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), - UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), - UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), - UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), - UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), - UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), - UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) -}; - -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) -{ - int i; - uint64_t temp1, temp2, W[80]; - uint64_t A, B, C, D, E, F, G, H; - -#define SHR(x,n) (x >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) - -#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) -#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) - -#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) -#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - - for( i = 0; i < 16; i++ ) - { - GET_UINT64_BE( W[i], data, i << 3 ); - } - - for( ; i < 80; i++ ) - { - W[i] = S1(W[i - 2]) + W[i - 7] + - S0(W[i - 15]) + W[i - 16]; - } - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - F = ctx->state[5]; - G = ctx->state[6]; - H = ctx->state[7]; - i = 0; - - do - { - P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; - P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; - P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; - P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; - P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; - P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; - P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; - P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; - } - while( i < 80 ); - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; - ctx->state[5] += F; - ctx->state[6] += G; - ctx->state[7] += H; -} -#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ - -/* - * SHA-512 process buffer - */ -void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, - size_t ilen ) -{ - size_t fill; - unsigned int left; - - if( ilen == 0 ) - return; - - left = (unsigned int) (ctx->total[0] & 0x7F); - fill = 128 - left; - - ctx->total[0] += (uint64_t) ilen; - - if( ctx->total[0] < (uint64_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha512_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 128 ) - { - mbedtls_sha512_process( ctx, input ); - input += 128; - ilen -= 128; - } - - if( ilen > 0 ) - memcpy( (void *) (ctx->buffer + left), input, ilen ); -} - -static const unsigned char sha512_padding[128] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-512 final digest - */ -void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ) -{ - size_t last, padn; - uint64_t high, low; - unsigned char msglen[16]; - - high = ( ctx->total[0] >> 61 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT64_BE( high, msglen, 0 ); - PUT_UINT64_BE( low, msglen, 8 ); - - last = (size_t)( ctx->total[0] & 0x7F ); - padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); - - mbedtls_sha512_update( ctx, sha512_padding, padn ); - mbedtls_sha512_update( ctx, msglen, 16 ); - - PUT_UINT64_BE( ctx->state[0], output, 0 ); - PUT_UINT64_BE( ctx->state[1], output, 8 ); - PUT_UINT64_BE( ctx->state[2], output, 16 ); - PUT_UINT64_BE( ctx->state[3], output, 24 ); - PUT_UINT64_BE( ctx->state[4], output, 32 ); - PUT_UINT64_BE( ctx->state[5], output, 40 ); - - if( ctx->is384 == 0 ) - { - PUT_UINT64_BE( ctx->state[6], output, 48 ); - PUT_UINT64_BE( ctx->state[7], output, 56 ); - } -} - -#endif /* !MBEDTLS_SHA512_ALT */ - -/* - * output = SHA-512( input buffer ) - */ -void mbedtls_sha512( const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ) -{ - mbedtls_sha512_context ctx; - - mbedtls_sha512_init( &ctx ); - mbedtls_sha512_starts( &ctx, is384 ); - mbedtls_sha512_update( &ctx, input, ilen ); - mbedtls_sha512_finish( &ctx, output ); - mbedtls_sha512_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) - -/* - * FIPS-180-2 test vectors - */ -static const unsigned char sha512_test_buf[3][113] = -{ - { "abc" }, - { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, - { "" } -}; - -static const int sha512_test_buflen[3] = -{ - 3, 112, 1000 -}; - -static const unsigned char sha512_test_sum[6][64] = -{ - /* - * SHA-384 test vectors - */ - { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, - 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, - 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, - 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, - 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, - 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, - { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, - 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, - 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, - 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, - 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, - 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, - { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, - 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, - 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, - 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, - 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, - 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, - - /* - * SHA-512 test vectors - */ - { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, - 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, - 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, - 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, - 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, - 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, - 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, - 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, - { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, - 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, - 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, - 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, - 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, - 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, - 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, - 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, - { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, - 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, - 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, - 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, - 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, - 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, - 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, - 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } -}; - -/* - * Checkup routine - */ -int mbedtls_sha512_self_test( int verbose ) -{ - int i, j, k, buflen, ret = 0; - unsigned char *buf; - unsigned char sha512sum[64]; - mbedtls_sha512_context ctx; - - buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); - if( NULL == buf ) - { - if( verbose != 0 ) - mbedtls_printf( "Buffer allocation failed\n" ); - - return( 1 ); - } - - mbedtls_sha512_init( &ctx ); - - for( i = 0; i < 6; i++ ) - { - j = i % 3; - k = i < 3; - - if( verbose != 0 ) - mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); - - mbedtls_sha512_starts( &ctx, k ); - - if( j == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - mbedtls_sha512_update( &ctx, buf, buflen ); - } - else - mbedtls_sha512_update( &ctx, sha512_test_buf[j], - sha512_test_buflen[j] ); - - mbedtls_sha512_finish( &ctx, sha512sum ); - - if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_sha512_free( &ctx ); - mbedtls_free( buf ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_SHA512_C */ diff --git a/components/security/mbedtls/src/ssl_cache.c b/components/security/mbedtls/src/ssl_cache.c deleted file mode 100644 index 9b62de2d..00000000 --- a/components/security/mbedtls/src/ssl_cache.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * SSL session cache implementation - * - * 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) - */ -/* - * These session callbacks use a simple chained list - * to store and retrieve the session information. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_CACHE_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/ssl_cache.h" - -#include - -void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) -{ - memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); - - cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; - cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &cache->mutex ); -#endif -} - -int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) -{ - int ret = 1; -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t = mbedtls_time( NULL ); -#endif - mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; - mbedtls_ssl_cache_entry *cur, *entry; - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) - return( 1 ); -#endif - - cur = cache->chain; - entry = NULL; - - while( cur != NULL ) - { - entry = cur; - cur = cur->next; - -#if defined(MBEDTLS_HAVE_TIME) - if( cache->timeout != 0 && - (int) ( t - entry->timestamp ) > cache->timeout ) - continue; -#endif - - if( session->ciphersuite != entry->session.ciphersuite || - session->compression != entry->session.compression || - session->id_len != entry->session.id_len ) - continue; - - if( memcmp( session->id, entry->session.id, - entry->session.id_len ) != 0 ) - continue; - - memcpy( session->master, entry->session.master, 48 ); - - session->verify_result = entry->session.verify_result; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - /* - * Restore peer certificate (without rest of the original chain) - */ - if( entry->peer_cert.p != NULL ) - { - if( ( session->peer_cert = mbedtls_calloc( 1, - sizeof(mbedtls_x509_crt) ) ) == NULL ) - { - ret = 1; - goto exit; - } - - mbedtls_x509_crt_init( session->peer_cert ); - if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, - entry->peer_cert.len ) != 0 ) - { - mbedtls_free( session->peer_cert ); - session->peer_cert = NULL; - ret = 1; - goto exit; - } - } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - ret = 0; - goto exit; - } - -exit: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) - ret = 1; -#endif - - return( ret ); -} - -int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) -{ - int ret = 1; -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t = time( NULL ), oldest = 0; - mbedtls_ssl_cache_entry *old = NULL; -#endif - mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; - mbedtls_ssl_cache_entry *cur, *prv; - int count = 0; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) - return( ret ); -#endif - - cur = cache->chain; - prv = NULL; - - while( cur != NULL ) - { - count++; - -#if defined(MBEDTLS_HAVE_TIME) - if( cache->timeout != 0 && - (int) ( t - cur->timestamp ) > cache->timeout ) - { - cur->timestamp = t; - break; /* expired, reuse this slot, update timestamp */ - } -#endif - - if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) - break; /* client reconnected, keep timestamp for session id */ - -#if defined(MBEDTLS_HAVE_TIME) - if( oldest == 0 || cur->timestamp < oldest ) - { - oldest = cur->timestamp; - old = cur; - } -#endif - - prv = cur; - cur = cur->next; - } - - if( cur == NULL ) - { -#if defined(MBEDTLS_HAVE_TIME) - /* - * Reuse oldest entry if max_entries reached - */ - if( count >= cache->max_entries ) - { - if( old == NULL ) - { - ret = 1; - goto exit; - } - - cur = old; - } -#else /* MBEDTLS_HAVE_TIME */ - /* - * Reuse first entry in chain if max_entries reached, - * but move to last place - */ - if( count >= cache->max_entries ) - { - if( cache->chain == NULL ) - { - ret = 1; - goto exit; - } - - cur = cache->chain; - cache->chain = cur->next; - cur->next = NULL; - prv->next = cur; - } -#endif /* MBEDTLS_HAVE_TIME */ - else - { - /* - * max_entries not reached, create new entry - */ - cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); - if( cur == NULL ) - { - ret = 1; - goto exit; - } - - if( prv == NULL ) - cache->chain = cur; - else - prv->next = cur; - } - -#if defined(MBEDTLS_HAVE_TIME) - cur->timestamp = t; -#endif - } - - memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - /* - * If we're reusing an entry, free its certificate first - */ - if( cur->peer_cert.p != NULL ) - { - mbedtls_free( cur->peer_cert.p ); - memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); - } - - /* - * Store peer certificate - */ - if( session->peer_cert != NULL ) - { - cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len ); - if( cur->peer_cert.p == NULL ) - { - ret = 1; - goto exit; - } - - memcpy( cur->peer_cert.p, session->peer_cert->raw.p, - session->peer_cert->raw.len ); - cur->peer_cert.len = session->peer_cert->raw.len; - - cur->session.peer_cert = NULL; - } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - ret = 0; - -exit: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) - ret = 1; -#endif - - return( ret ); -} - -#if defined(MBEDTLS_HAVE_TIME) -void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) -{ - if( timeout < 0 ) timeout = 0; - - cache->timeout = timeout; -} -#endif /* MBEDTLS_HAVE_TIME */ - -void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) -{ - if( max < 0 ) max = 0; - - cache->max_entries = max; -} - -void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) -{ - mbedtls_ssl_cache_entry *cur, *prv; - - cur = cache->chain; - - while( cur != NULL ) - { - prv = cur; - cur = cur->next; - - mbedtls_ssl_session_free( &prv->session ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_free( prv->peer_cert.p ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - mbedtls_free( prv ); - } - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &cache->mutex ); -#endif -} - -#endif /* MBEDTLS_SSL_CACHE_C */ diff --git a/components/security/mbedtls/src/ssl_ciphersuites.c b/components/security/mbedtls/src/ssl_ciphersuites.c deleted file mode 100644 index 516e647b..00000000 --- a/components/security/mbedtls/src/ssl_ciphersuites.c +++ /dev/null @@ -1,1872 +0,0 @@ -/** - * \file ssl_ciphersuites.c - * - * \brief SSL ciphersuites for mbed TLS - * - * 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_SSL_TLS_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#endif - -#include "mbedtls/ssl_ciphersuites.h" -#include "mbedtls/ssl.h" - -#include - -/* - * Ordered from most preferred to least preferred in terms of security. - * - * Current rule (except rc4, weak and null which come last): - * 1. By key exchange: - * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK - * 2. By key length and cipher: - * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES - * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 - * 4. By hash function used when relevant - * 5. By key exchange/auth again: EC > non-EC - */ -static const int ciphersuite_preference[] = -{ -#if defined(MBEDTLS_SSL_CIPHERSUITES) - MBEDTLS_SSL_CIPHERSUITES, -#else - -#if !defined(MBEDTLS_IOT_SPECIFIC) - /* All AES-256 ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, - - /* All CAMELLIA-256 ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, - - /* All AES-128 ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, - - /* All CAMELLIA-128 ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, - - /* All remaining >= 128-bit ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, - - /* The PSK ephemeral suites */ - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, - MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, - - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, - MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, - - MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, - - /* The ECJPAKE suite */ - MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, -#endif /* !MBEDTLS_IOT_SPECIFIC */ - - /* All AES-256 suites */ -#if !defined(MBEDTLS_IOT_SPECIFIC) - MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_RSA_WITH_AES_256_CCM, -#endif /* !MBEDTLS_IOT_SPECIFIC */ - MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, -#if !defined(MBEDTLS_IOT_SPECIFIC) - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, -#endif /* !MBEDTLS_IOT_SPECIFIC */ - -#if !defined(MBEDTLS_IOT_SPECIFIC) - /* All CAMELLIA-256 suites */ - MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, -#endif /* !MBEDTLS_IOT_SPECIFIC */ - - /* All AES-128 suites */ -#if !defined(MBEDTLS_IOT_SPECIFIC) - MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_128_CCM, -#endif /* !MBEDTLS_IOT_SPECIFIC */ - MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, -#if !defined(MBEDTLS_IOT_SPECIFIC) - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, -#endif /* !MBEDTLS_IOT_SPECIFIC */ - -#if !defined(MBEDTLS_IOT_SPECIFIC) - /* All CAMELLIA-128 suites */ - MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - - /* All remaining >= 128-bit suites */ - MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - - /* The RSA PSK suites */ - MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, - - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, - - MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, - - /* The PSK suites */ - MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_PSK_WITH_AES_256_CCM, - MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, - - MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_PSK_WITH_AES_128_CCM, - MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, - - MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, - - /* RC4 suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, - MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, - - /* Weak suites */ - MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, - MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, - - /* NULL suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, - MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, - MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, - MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, - - MBEDTLS_TLS_RSA_WITH_NULL_SHA256, - MBEDTLS_TLS_RSA_WITH_NULL_SHA, - MBEDTLS_TLS_RSA_WITH_NULL_MD5, - MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, - MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, - MBEDTLS_TLS_PSK_WITH_NULL_SHA384, - MBEDTLS_TLS_PSK_WITH_NULL_SHA256, - MBEDTLS_TLS_PSK_WITH_NULL_SHA, -#endif /* !MBEDTLS_IOT_SPECIFIC */ - -#endif /* MBEDTLS_SSL_CIPHERSUITES */ - 0 -}; - -static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = -{ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_MD5_C) - { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_MD5_C) - { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", - MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", - MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ -#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ - - { 0, "", - MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, - 0, 0, 0, 0, 0 } -}; - -#if defined(MBEDTLS_SSL_CIPHERSUITES) -const int *mbedtls_ssl_list_ciphersuites( void ) -{ - return( ciphersuite_preference ); -} -#else -#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ - sizeof( ciphersuite_definitions[0] ) -static int supported_ciphersuites[MAX_CIPHERSUITES]; -static int supported_init = 0; - -const int *mbedtls_ssl_list_ciphersuites( void ) -{ - /* - * On initial call filter out all ciphersuites not supported by current - * build based on presence in the ciphersuite_definitions. - */ - if( supported_init == 0 ) - { - const int *p; - int *q; - - for( p = ciphersuite_preference, q = supported_ciphersuites; - *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; - p++ ) - { -#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) - const mbedtls_ssl_ciphersuite_t *cs_info; - if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && - cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 ) -#else - if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL ) -#endif - *(q++) = *p; - } - *q = 0; - - supported_init = 1; - } - - return( supported_ciphersuites ); -} -#endif /* MBEDTLS_SSL_CIPHERSUITES */ - -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( - const char *ciphersuite_name ) -{ - const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; - - if( NULL == ciphersuite_name ) - return( NULL ); - - while( cur->id != 0 ) - { - if( 0 == strcmp( cur->name, ciphersuite_name ) ) - return( cur ); - - cur++; - } - - return( NULL ); -} - -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) -{ - const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; - - while( cur->id != 0 ) - { - if( cur->id == ciphersuite ) - return( cur ); - - cur++; - } - - return( NULL ); -} - -const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) -{ - const mbedtls_ssl_ciphersuite_t *cur; - - cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); - - if( cur == NULL ) - return( "unknown" ); - - return( cur->name ); -} - -int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) -{ - const mbedtls_ssl_ciphersuite_t *cur; - - cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); - - if( cur == NULL ) - return( 0 ); - - return( cur->id ); -} - -#if defined(MBEDTLS_PK_C) -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - return( MBEDTLS_PK_RSA ); - - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - return( MBEDTLS_PK_ECDSA ); - - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - return( MBEDTLS_PK_ECKEY ); - - default: - return( MBEDTLS_PK_NONE ); - } -} -#endif /* MBEDTLS_PK_C */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) -int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_PSK: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/components/security/mbedtls/src/ssl_cli.c b/components/security/mbedtls/src/ssl_cli.c deleted file mode 100644 index 223823b3..00000000 --- a/components/security/mbedtls/src/ssl_cli.c +++ /dev/null @@ -1,3405 +0,0 @@ -/* - * SSLv3/TLSv1 client-side 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_SSL_CLI_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" - -#include - -#include - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -/* 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_SSL_SERVER_NAME_INDICATION) -static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t hostname_len; - - *olen = 0; - - if( ssl->hostname == NULL ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", - ssl->hostname ) ); - - hostname_len = strlen( ssl->hostname ); - - if( end < p || (size_t)( end - p ) < hostname_len + 9 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - /* - * struct { - * NameType name_type; - * select (name_type) { - * case host_name: HostName; - * } name; - * } ServerName; - * - * enum { - * host_name(0), (255) - * } NameType; - * - * opaque HostName<1..2^16-1>; - * - * struct { - * ServerName server_name_list<1..2^16-1> - * } ServerNameList; - */ - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); - - *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF ); - - *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); - *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( hostname_len ) & 0xFF ); - - memcpy( p, ssl->hostname, hostname_len ); - - *olen = hostname_len + 9; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); - - if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - /* - * Secure renegotiation - */ - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); - - *p++ = 0x00; - *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; - *p++ = ssl->verify_data_len & 0xFF; - - memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); - - *olen = 5 + ssl->verify_data_len; -} -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/* - * Only if we handle at least one key exchange that needs signatures. - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t sig_alg_len = 0; - const int *md; -#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) - unsigned char *sig_alg_list = buf + 6; -#endif - - *olen = 0; - - if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); - - for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) - { -#if defined(MBEDTLS_ECDSA_C) - sig_alg_len += 2; -#endif -#if defined(MBEDTLS_RSA_C) - sig_alg_len += 2; -#endif - } - - if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - /* - * Prepare signature_algorithms extension (TLS 1.2) - */ - sig_alg_len = 0; - - for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) - { -#if defined(MBEDTLS_ECDSA_C) - sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); - sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; -#endif -#if defined(MBEDTLS_RSA_C) - sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); - sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; -#endif - } - - /* - * enum { - * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), - * sha512(6), (255) - * } HashAlgorithm; - * - * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } - * SignatureAlgorithm; - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - * - * SignatureAndHashAlgorithm - * supported_signature_algorithms<2..2^16-2>; - */ - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); - - *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); - - *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); - - *olen = 6 + sig_alg_len; -} -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - unsigned char *elliptic_curve_list = p + 6; - size_t elliptic_curve_len = 0; - const mbedtls_ecp_curve_info *info; -#if defined(MBEDTLS_ECP_C) - const mbedtls_ecp_group_id *grp_id; -#else - ((void) ssl); -#endif - - *olen = 0; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); - -#if defined(MBEDTLS_ECP_C) - for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) - { - info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); -#else - for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) - { -#endif - if( info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) ); - return; - } - - elliptic_curve_len += 2; - } - - if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - elliptic_curve_len = 0; - -#if defined(MBEDTLS_ECP_C) - for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) - { - info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); -#else - for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) - { -#endif - elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; - elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; - } - - if( elliptic_curve_len == 0 ) - return; - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); - - *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); - - *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); - - *olen = 6 + elliptic_curve_len; -} - -static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); - - if( end < p || (size_t)( end - p ) < 6 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); - - *p++ = 0x00; - *p++ = 2; - - *p++ = 1; - *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; - - *olen = 6; -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - int ret; - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t kkpp_len; - - *olen = 0; - - /* Skip costly extension if we can't use EC J-PAKE anyway */ - if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) ); - - if( end - p < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); - - /* - * We may need to send ClientHello multiple times for Hello verification. - * We don't want to compute fresh values every time (both for performance - * and consistency reasons), so cache the extension content. - */ - if( ssl->handshake->ecjpake_cache == NULL || - ssl->handshake->ecjpake_cache_len == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); - - ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, - p + 2, end - p - 2, &kkpp_len, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); - return; - } - - ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); - if( ssl->handshake->ecjpake_cache == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); - return; - } - - memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); - ssl->handshake->ecjpake_cache_len = kkpp_len; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); - - kkpp_len = ssl->handshake->ecjpake_cache_len; - - if( (size_t)( end - p - 2 ) < kkpp_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); - } - - *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); - - *olen = kkpp_len + 4; -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); - - if( end < p || (size_t)( end - p ) < 5 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); - - *p++ = 0x00; - *p++ = 1; - - *p++ = ssl->conf->mfl_code; - - *olen = 5; -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); - - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || - ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac " - "extension" ) ); - - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " - "extension" ) ); - - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t tlen = ssl->session_negotiate->ticket_len; - - *olen = 0; - - if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); - - if( end < p || (size_t)( end - p ) < 4 + tlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); - - *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( tlen ) & 0xFF ); - - *olen = 4; - - if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) ); - - memcpy( p, ssl->session_negotiate->ticket, tlen ); - - *olen += tlen; -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_ALPN) -static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t alpnlen = 0; - const char **cur; - - *olen = 0; - - if( ssl->conf->alpn_list == NULL ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); - - for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) - alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1; - - if( end < p || (size_t)( end - p ) < 6 + alpnlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - */ - - /* Skip writing extension and list length for now */ - p += 4; - - for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) - { - *p = (unsigned char)( strlen( *cur ) & 0xFF ); - memcpy( p + 1, *cur, *p ); - p += 1 + *p; - } - - *olen = p - buf; - - /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ - buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); - buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); - - /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ - buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); - buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); -} -#endif /* MBEDTLS_SSL_ALPN */ - -/* - * Generate random bytes for ClientHello - */ -static int ssl_generate_random( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *p = ssl->handshake->randbytes; -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t; -#endif - - /* - * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->verify_cookie != NULL ) - { - return( 0 ); - } -#endif - -#if defined(MBEDTLS_HAVE_TIME) - t = mbedtls_time( NULL ); - *p++ = (unsigned char)( t >> 24 ); - *p++ = (unsigned char)( t >> 16 ); - *p++ = (unsigned char)( t >> 8 ); - *p++ = (unsigned char)( t ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); -#else - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) - return( ret ); - - p += 4; -#endif /* MBEDTLS_HAVE_TIME */ - - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t i, n, olen, ext_len = 0; - unsigned char *buf; - unsigned char *p, *q; - unsigned char offer_compress; - const int *ciphersuites; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); - - if( ssl->conf->f_rng == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); - return( MBEDTLS_ERR_SSL_NO_RNG ); - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) -#endif - { - ssl->major_ver = ssl->conf->min_major_ver; - ssl->minor_ver = ssl->conf->min_minor_ver; - } - - if( ssl->conf->max_major_ver == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, " - "consider using mbedtls_ssl_config_defaults()" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 highest version supported - * 6 . 9 current UNIX time - * 10 . 37 random bytes - */ - buf = ssl->out_msg; - p = buf + 4; - - mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, - ssl->conf->transport, p ); - p += 2; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", - buf[4], buf[5] ) ); - - if( ( ret = ssl_generate_random( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); - return( ret ); - } - - memcpy( p, ssl->handshake->randbytes, 32 ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); - p += 32; - - /* - * 38 . 38 session id length - * 39 . 39+n session id - * 39+n . 39+n DTLS only: cookie length (1 byte) - * 40+n . .. DTSL only: cookie - * .. . .. ciphersuitelist length (2 bytes) - * .. . .. ciphersuitelist - * .. . .. compression methods length (1 byte) - * .. . .. compression methods - * .. . .. extensions length (2 bytes) - * .. . .. extensions - */ - n = ssl->session_negotiate->id_len; - - if( n < 16 || n > 32 || -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || -#endif - ssl->handshake->resume == 0 ) - { - n = 0; - } - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - /* - * RFC 5077 section 3.4: "When presenting a ticket, the client MAY - * generate and include a Session ID in the TLS ClientHello." - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) -#endif - { - if( ssl->session_negotiate->ticket != NULL && - ssl->session_negotiate->ticket_len != 0 ) - { - ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 ); - - if( ret != 0 ) - return( ret ); - - ssl->session_negotiate->id_len = n = 32; - } - } -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - - *p++ = (unsigned char) n; - - for( i = 0; i < n; i++ ) - *p++ = ssl->session_negotiate->id[i]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); - - /* - * DTLS cookie - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( ssl->handshake->verify_cookie == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); - *p++ = 0; - } - else - { - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", - ssl->handshake->verify_cookie, - ssl->handshake->verify_cookie_len ); - - *p++ = ssl->handshake->verify_cookie_len; - memcpy( p, ssl->handshake->verify_cookie, - ssl->handshake->verify_cookie_len ); - p += ssl->handshake->verify_cookie_len; - } - } -#endif - - /* - * Ciphersuite list - */ - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; - - /* Skip writing ciphersuite length for now */ - n = 0; - q = p; - p += 2; - - for( i = 0; ciphersuites[i] != 0; i++ ) - { - ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); - - if( ciphersuite_info == NULL ) - continue; - - if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver || - ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver ) - continue; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) - continue; -#endif - -#if defined(MBEDTLS_ARC4_C) - if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) - continue; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && - mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - continue; -#endif - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", - ciphersuites[i] ) ); - - n++; - *p++ = (unsigned char)( ciphersuites[i] >> 8 ); - *p++ = (unsigned char)( ciphersuites[i] ); - } - - /* - * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) -#endif - { - *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); - *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); - n++; - } - - /* Some versions of OpenSSL don't handle it correctly if not at end */ -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); - *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ); - *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ); - n++; - } -#endif - - *q++ = (unsigned char)( n >> 7 ); - *q++ = (unsigned char)( n << 1 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); - -#if defined(MBEDTLS_ZLIB_SUPPORT) - offer_compress = 1; -#else - offer_compress = 0; -#endif - - /* - * We don't support compression with DTLS right now: is many records come - * in the same datagram, uncompressing one could overwrite the next one. - * We don't want to add complexity for handling that case unless there is - * an actual need for it. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - offer_compress = 0; -#endif - - if( offer_compress ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", - MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) ); - - *p++ = 2; - *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; - *p++ = MBEDTLS_SSL_COMPRESS_NULL; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", - MBEDTLS_SSL_COMPRESS_NULL ) ); - - *p++ = 1; - *p++ = MBEDTLS_SSL_COMPRESS_NULL; - } - - // First write extensions, then the total length - // -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; - - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ALPN) - ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - - /* olen unused if all extensions are disabled */ - ((void) olen); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", - ext_len ) ); - - if( ext_len > 0 ) - { - *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ext_len ) & 0xFF ); - p += ext_len; - } - - ssl->out_msglen = p - buf; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_send_flight_completed( ssl ); -#endif - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); - - return( 0 ); -} - -static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - int ret; - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - /* Check verify-data in constant-time. The length OTOH is no secret */ - if( len != 1 + ssl->verify_data_len * 2 || - buf[0] != ssl->verify_data_len * 2 || - mbedtls_ssl_safer_memcmp( buf + 1, - ssl->own_verify_data, ssl->verify_data_len ) != 0 || - mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len, - ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - } - else -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - { - if( len != 1 || buf[0] != 0x00 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - } - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - /* - * server should use the extension only if we did, - * and if so the server's value should match ours (and len is always 1) - */ - if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || - len != 1 || - buf[0] != ssl->conf->mfl_code ) - { - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || - len != 0 ) - { - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ((void) buf); - - ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || - len != 0 ) - { - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ((void) buf); - - ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || - len != 0 ) - { - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ((void) buf); - - ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || - len != 0 ) - { - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ((void) buf); - - ssl->handshake->new_session_ticket = 1; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - size_t list_size; - const unsigned char *p; - - list_size = buf[0]; - if( list_size + 1 != len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - p = buf + 1; - while( list_size > 0 ) - { - if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || - p[0] == MBEDTLS_ECP_PF_COMPRESSED ) - { -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) - ssl->handshake->ecdh_ctx.point_format = p[0]; -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl->handshake->ecjpake_ctx.point_format = p[0]; -#endif - MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); - return( 0 ); - } - - list_size--; - p++; - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - int ret; - - if( ssl->transform_negotiate->ciphersuite_info->key_exchange != - MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); - return( 0 ); - } - - /* If we got here, we no longer need our cached extension */ - mbedtls_free( ssl->handshake->ecjpake_cache ); - ssl->handshake->ecjpake_cache = NULL; - ssl->handshake->ecjpake_cache_len = 0; - - if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, - buf, len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_ALPN) -static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - size_t list_len, name_len; - const char **p; - - /* If we didn't send it, the server shouldn't send it */ - if( ssl->conf->alpn_list == NULL ) - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - * - * the "ProtocolNameList" MUST contain exactly one "ProtocolName" - */ - - /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ - if( len < 4 ) - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - - list_len = ( buf[0] << 8 ) | buf[1]; - if( list_len != len - 2 ) - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - - name_len = buf[2]; - if( name_len != list_len - 1 ) - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - - /* Check that the server chosen protocol was in our list and save it */ - for( p = ssl->conf->alpn_list; *p != NULL; p++ ) - { - if( name_len == strlen( *p ) && - memcmp( buf + 3, *p, name_len ) == 0 ) - { - ssl->alpn_chosen = *p; - return( 0 ); - } - } - - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); -} -#endif /* MBEDTLS_SSL_ALPN */ - -/* - * Parse HelloVerifyRequest. Only called after verifying the HS type. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) -static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) -{ - const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - int major_ver, minor_ver; - unsigned char cookie_len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); - - /* - * struct { - * ProtocolVersion server_version; - * opaque cookie<0..2^8-1>; - * } HelloVerifyRequest; - */ - MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); - mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); - p += 2; - - /* - * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) - * even is lower than our min version. - */ - if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || - minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || - major_ver > ssl->conf->max_major_ver || - minor_ver > ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); - } - - cookie_len = *p++; - MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); - - if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, - ( "cookie length does not match incoming message size" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - mbedtls_free( ssl->handshake->verify_cookie ); - - ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); - if( ssl->handshake->verify_cookie == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - memcpy( ssl->handshake->verify_cookie, p, cookie_len ); - ssl->handshake->verify_cookie_len = cookie_len; - - /* Start over at ClientHello */ - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; - mbedtls_ssl_reset_checksum( ssl ); - - mbedtls_ssl_recv_flight_completed( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) -{ - int ret, i; - size_t n; - size_t ext_len; - unsigned char *buf, *ext; - unsigned char comp; -#if defined(MBEDTLS_ZLIB_SUPPORT) - int accept_comp; -#endif -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renegotiation_info_seen = 0; -#endif - int handshake_failure = 0; - const mbedtls_ssl_ciphersuite_t *suite_info; -#if defined(MBEDTLS_DEBUG_C) - uint32_t t; -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); - - buf = ssl->in_msg; - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - ssl->renego_records_seen++; - - if( ssl->conf->renego_max_records >= 0 && - ssl->renego_records_seen > ssl->conf->renego_max_records ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " - "but not honored by server" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); - return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); - return( ssl_parse_hello_verify_request( ssl ) ); - } - else - { - /* We made it through the verification process */ - mbedtls_free( ssl->handshake->verify_cookie ); - ssl->handshake->verify_cookie = NULL; - ssl->handshake->verify_cookie_len = 0; - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || - buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - /* - * 0 . 1 server_version - * 2 . 33 random (maybe including 4 bytes of Unix time) - * 34 . 34 session_id length = n - * 35 . 34+n session_id - * 35+n . 36+n cipher_suite - * 37+n . 37+n compression_method - * - * 38+n . 39+n extensions length (optional) - * 40+n . .. extensions - */ - buf += mbedtls_ssl_hs_hdr_len( ssl ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); - mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, - ssl->conf->transport, buf + 0 ); - - if( ssl->major_ver < ssl->conf->min_major_ver || - ssl->minor_ver < ssl->conf->min_minor_ver || - ssl->major_ver > ssl->conf->max_major_ver || - ssl->minor_ver > ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - " - " min: [%d:%d], server: [%d:%d], max: [%d:%d]", - ssl->conf->min_major_ver, ssl->conf->min_minor_ver, - ssl->major_ver, ssl->minor_ver, - ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); - } - -#if defined(MBEDTLS_DEBUG_C) - t = ( (uint32_t) buf[2] << 24 ) - | ( (uint32_t) buf[3] << 16 ) - | ( (uint32_t) buf[4] << 8 ) - | ( (uint32_t) buf[5] ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); -#endif - - memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); - - n = buf[34]; - - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); - - if( n > 32 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) - { - ext_len = ( ( buf[38 + n] << 8 ) - | ( buf[39 + n] ) ); - - if( ( ext_len > 0 && ext_len < 4 ) || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - } - else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) - { - ext_len = 0; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - /* ciphersuite (used later) */ - i = ( buf[35 + n] << 8 ) | buf[36 + n]; - - /* - * Read and check compression - */ - comp = buf[37 + n]; - -#if defined(MBEDTLS_ZLIB_SUPPORT) - /* See comments in ssl_write_client_hello() */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - accept_comp = 0; - else -#endif - accept_comp = 1; - - if( comp != MBEDTLS_SSL_COMPRESS_NULL && - ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) -#else /* MBEDTLS_ZLIB_SUPPORT */ - if( comp != MBEDTLS_SSL_COMPRESS_NULL ) -#endif/* MBEDTLS_ZLIB_SUPPORT */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* - * Initialize update checksum functions - */ - ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); - - if( ssl->transform_negotiate->ciphersuite_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); - - /* - * Check if the session can be resumed - */ - if( ssl->handshake->resume == 0 || n == 0 || -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || -#endif - ssl->session_negotiate->ciphersuite != i || - ssl->session_negotiate->compression != comp || - ssl->session_negotiate->id_len != n || - memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) - { - ssl->state++; - ssl->handshake->resume = 0; -#if defined(MBEDTLS_HAVE_TIME) - ssl->session_negotiate->start = mbedtls_time( NULL ); -#endif - ssl->session_negotiate->ciphersuite = i; - ssl->session_negotiate->compression = comp; - ssl->session_negotiate->id_len = n; - memcpy( ssl->session_negotiate->id, buf + 35, n ); - } - else - { - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", - ssl->handshake->resume ? "a" : "no" ) ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); - - suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); - if( suite_info == NULL -#if defined(MBEDTLS_ARC4_C) - || ( ssl->conf->arc4_disabled && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); - - i = 0; - while( 1 ) - { - if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == - ssl->session_negotiate->ciphersuite ) - { - break; - } - } - - if( comp != MBEDTLS_SSL_COMPRESS_NULL -#if defined(MBEDTLS_ZLIB_SUPPORT) - && comp != MBEDTLS_SSL_COMPRESS_DEFLATE -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - ssl->session_negotiate->compression = comp; - - ext = buf + 40 + n; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); - - while( ext_len ) - { - unsigned int ext_id = ( ( ext[0] << 8 ) - | ( ext[1] ) ); - unsigned int ext_size = ( ( ext[2] << 8 ) - | ( ext[3] ) ); - - if( ext_size + 4 > ext_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - switch( ext_id ) - { - case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - renegotiation_info_seen = 1; -#endif - - if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, - ext_size ) ) != 0 ) - return( ret ); - - break; - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); - - if( ( ret = ssl_parse_max_fragment_length_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); - - if( ( ret = ssl_parse_truncated_hmac_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); - - if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) ); - - if( ( ret = ssl_parse_extended_ms_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_TLS_EXT_SESSION_TICKET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); - - if( ( ret = ssl_parse_session_ticket_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) ); - - if( ( ret = ssl_parse_supported_point_formats_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); - - if( ( ret = ssl_parse_ecjpake_kkpp( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_ALPN) - case MBEDTLS_TLS_EXT_ALPN: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); - - if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) - return( ret ); - - break; -#endif /* MBEDTLS_SSL_ALPN */ - - default: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", - ext_id ) ); - } - - ext_len -= 4 + ext_size; - ext += 4 + ext_size; - - if( ext_len > 0 && ext_len < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - } - - /* - * Renegotiation security checks - */ - if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); - handshake_failure = 1; - } -#if defined(MBEDTLS_SSL_RENEGOTIATION) - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && - renegotiation_info_seen == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); - handshake_failure = 1; - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); - handshake_failure = 1; - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - renegotiation_info_seen == 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); - handshake_failure = 1; - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - if( handshake_failure == 1 ) - { - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p, - unsigned char *end ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - /* - * Ephemeral DH parameters: - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); - return( ret ); - } - - if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d", - ssl->handshake->dhm_ctx.len * 8, - ssl->conf->dhm_min_bitlen ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) -{ - const mbedtls_ecp_curve_info *curve_info; - - curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); - if( curve_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); - -#if defined(MBEDTLS_ECP_C) - if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 ) -#else - if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || - ssl->handshake->ecdh_ctx.grp.nbits > 521 ) -#endif - return( -1 ); - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - /* - * Ephemeral ECDH parameters: - * - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; - */ - if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, - (const unsigned char **) p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); - return( ret ); - } - - if( ssl_check_server_ecdh_params( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t len; - ((void) ssl); - - /* - * PSK parameters: - * - * opaque psk_identity_hint<0..2^16-1>; - */ - len = (*p)[0] << 8 | (*p)[1]; - *p += 2; - - if( (*p) + len > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - /* - * Note: we currently ignore the PKS identity hint, as we only allow one - * PSK to be provisionned on the client. This could be changed later if - * someone needs that feature. - */ - *p += len; - ret = 0; - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -/* - * Generate a pre-master secret and encrypt it with the server's RSA key - */ -static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, - size_t offset, size_t *olen, - size_t pms_offset ) -{ - int ret; - size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; - unsigned char *p = ssl->handshake->premaster + pms_offset; - - if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - /* - * Generate (part of) the pre-master as - * struct { - * ProtocolVersion client_version; - * opaque random[46]; - * } PreMasterSecret; - */ - mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, - ssl->conf->transport, p ); - - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); - return( ret ); - } - - ssl->handshake->pmslen = 48; - - if( ssl->session_negotiate->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* - * Now write it out, encrypted - */ - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, - MBEDTLS_PK_RSA ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); - return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); - } - - if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, - p, ssl->handshake->pmslen, - ssl->out_msg + offset + len_bytes, olen, - MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); - return( ret ); - } - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( len_bytes == 2 ) - { - ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); - ssl->out_msg[offset+1] = (unsigned char)( *olen ); - *olen += 2; - } -#endif - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end, - mbedtls_md_type_t *md_alg, - mbedtls_pk_type_t *pk_alg ) -{ - ((void) ssl); - *md_alg = MBEDTLS_MD_NONE; - *pk_alg = MBEDTLS_PK_NONE; - - /* Only in TLS 1.2 */ - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - { - return( 0 ); - } - - if( (*p) + 2 > end ) - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - - /* - * Get hash algorithm - */ - if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported " - "HashAlgorithm %d", *(p)[0] ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - /* - * Get signature algorithm - */ - if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported " - "SignatureAlgorithm %d", (*p)[1] ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - /* - * Check if the hash is acceptable - */ - if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm " - "that was not offered" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); - *p += 2; - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) -{ - int ret; - const mbedtls_ecp_keypair *peer_key; - - if( ssl->session_negotiate->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, - MBEDTLS_PK_ECKEY ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); - return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); - } - - peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk ); - - if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, - MBEDTLS_ECDH_THEIRS ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); - return( ret ); - } - - if( ssl_check_server_ecdh_params( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) -{ - int ret; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - unsigned char *p, *end; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); - ssl->state++; - return( 0 ); - } - ((void) p); - ((void) end); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) - { - if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); - ssl->state++; - return( 0 ); - } - ((void) p); - ((void) end); -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* - * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server - * doesn't use a psk_identity_hint - */ - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) - { - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - ssl->record_read = 1; - goto exit; - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - end = ssl->in_msg + ssl->in_hslen; - MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } /* FALLTROUGH */ -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - ; /* nothing more to do */ - else -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) - { - if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) - { - size_t sig_len, hashlen; - unsigned char hash[64]; - mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - size_t params_len = p - params; - - /* - * Handle the digitally-signed structure - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - if( ssl_parse_signature_algorithm( ssl, &p, end, - &md_alg, &pk_alg ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) - { - pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); - - /* Default hash for ECDSA is SHA-1 */ - if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) - md_alg = MBEDTLS_MD_SHA1; - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * Read signature - */ - sig_len = ( p[0] << 8 ) | p[1]; - p += 2; - - if( end != p + sig_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); - - /* - * Compute the hash that has been signed - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( md_alg == MBEDTLS_MD_NONE ) - { - mbedtls_md5_context mbedtls_md5; - mbedtls_sha1_context mbedtls_sha1; - - mbedtls_md5_init( &mbedtls_md5 ); - mbedtls_sha1_init( &mbedtls_sha1 ); - - hashlen = 36; - - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); - */ - mbedtls_md5_starts( &mbedtls_md5 ); - mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); - mbedtls_md5_update( &mbedtls_md5, params, params_len ); - mbedtls_md5_finish( &mbedtls_md5, hash ); - - mbedtls_sha1_starts( &mbedtls_sha1 ); - mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); - mbedtls_sha1_update( &mbedtls_sha1, params, params_len ); - mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); - - mbedtls_md5_free( &mbedtls_md5 ); - mbedtls_sha1_free( &mbedtls_sha1 ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( md_alg != MBEDTLS_MD_NONE ) - { - mbedtls_md_context_t ctx; - - mbedtls_md_init( &ctx ); - - /* Info from md_alg will be used instead */ - hashlen = 0; - - /* - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * }; - */ - if( ( ret = mbedtls_md_setup( &ctx, - mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); - return( ret ); - } - - mbedtls_md_starts( &ctx ); - mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); - mbedtls_md_update( &ctx, params, params_len ); - mbedtls_md_finish( &ctx, hash ); - mbedtls_md_free( &ctx ); - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); - - if( ssl->session_negotiate->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* - * Verify signature - */ - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); - } - - if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, - md_alg, hash, hashlen, p, sig_len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -exit: - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); - - return( 0 ); -} - -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else -static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *buf; - size_t n = 0; - size_t cert_type_len = 0, dn_len = 0; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); - ssl->state++; - return( 0 ); - } - - if( ssl->record_read == 0 ) - { - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - ssl->record_read = 1; - } - - ssl->client_auth = 0; - ssl->state++; - - if( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ) - ssl->client_auth++; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", - ssl->client_auth ? "a" : "no" ) ); - - if( ssl->client_auth == 0 ) - goto exit; - - ssl->record_read = 0; - - /* - * struct { - * ClientCertificateType certificate_types<1..2^8-1>; - * SignatureAndHashAlgorithm - * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only - * DistinguishedName certificate_authorities<0..2^16-1>; - * } CertificateRequest; - * - * Since we only support a single certificate on clients, let's just - * ignore all the information that's supposed to help us pick a - * certificate. - * - * We could check that our certificate matches the request, and bail out - * if it doesn't, but it's simpler to just send the certificate anyway, - * and give the server the opportunity to decide if it should terminate - * the connection when it doesn't like our certificate. - * - * Same goes for the hash in TLS 1.2's signature_algorithms: at this - * point we only have one hash available (see comments in - * write_certificate_verify), so let's just use what we have. - * - * However, we still minimally parse the message to check it is at least - * superficially sane. - */ - buf = ssl->in_msg; - - /* certificate_types */ - cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; - n = cert_type_len; - - if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); - } - - /* supported_signature_algorithms */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) - | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); -#if defined(MBEDTLS_DEBUG_C) - unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; - size_t i; - - for( i = 0; i < sig_alg_len; i += 2 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d,%d", sig_alg[i], sig_alg[i + 1] ) ); - } -#endif - - n += 2 + sig_alg_len; - - if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); - } - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - /* certificate_authorities */ - dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) - | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); - - n += dn_len; - if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); - } - -exit: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); - - return( 0 ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); - - if( ssl->record_read == 0 ) - { - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - } - ssl->record_read = 0; - - if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || - ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); - } - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_recv_flight_completed( ssl ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); - - return( 0 ); -} - -static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t i, n; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) - { - /* - * DHM key exchange -- send G^X mod P - */ - n = ssl->handshake->dhm_ctx.len; - - ssl->out_msg[4] = (unsigned char)( n >> 8 ); - ssl->out_msg[5] = (unsigned char)( n ); - i = 6; - - ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - &ssl->out_msg[i], n, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); - - if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, - ssl->handshake->premaster, - MBEDTLS_PREMASTER_SIZE, - &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) - { - /* - * ECDH key exchange -- send client public value - */ - i = 4; - - ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, - &n, - &ssl->out_msg[i], 1000, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); - - if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, - &ssl->handshake->pmslen, - ssl->handshake->premaster, - MBEDTLS_MPI_MAX_SIZE, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - /* - * opaque psk_identity<0..2^16-1>; - */ - if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - - i = 4; - n = ssl->conf->psk_identity_len; - - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " - "SSL buffer too short" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - ssl->out_msg[i++] = (unsigned char)( n >> 8 ); - ssl->out_msg[i++] = (unsigned char)( n ); - - memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len ); - i += ssl->conf->psk_identity_len; - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) - { - n = 0; - } - else -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) - return( ret ); - } - else -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - /* - * ClientDiffieHellmanPublic public (DHM send G^X mod P) - */ - n = ssl->handshake->dhm_ctx.len; - - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" - " or SSL buffer too short" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - ssl->out_msg[i++] = (unsigned char)( n >> 8 ); - ssl->out_msg[i++] = (unsigned char)( n ); - - ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - &ssl->out_msg[i], n, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - /* - * ClientECDiffieHellmanPublic public; - */ - ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, - &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) - { - i = 4; - if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) - return( ret ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - i = 4; - - ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); - return( ret ); - } - - ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, - ssl->handshake->premaster, 32, &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ - { - ((void) ciphersuite_info); - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->out_msglen = i + n; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); - - return( 0 ); -} - -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else -static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - size_t n = 0, offset = 0; - unsigned char hash[48]; - unsigned char *hash_start = hash; - mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; - unsigned int hashlen; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - if( mbedtls_ssl_own_key( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - - /* - * Make an RSA signature of the handshake digests - */ - ssl->handshake->calc_verify( ssl, hash ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - { - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(handshake_messages); - * - * sha_hash - * SHA(handshake_messages); - */ - hashlen = 36; - md_alg = MBEDTLS_MD_NONE; - - /* - * For ECDSA, default hash is SHA-1 only - */ - if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) - { - hash_start += 16; - hashlen -= 16; - md_alg = MBEDTLS_MD_SHA1; - } - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - /* - * digitally-signed struct { - * opaque handshake_messages[handshake_messages_length]; - * }; - * - * Taking shortcut here. We assume that the server always allows the - * PRF Hash function and has sent it in the allowed signature - * algorithms list received in the Certificate Request message. - * - * Until we encounter a server that does not, we will take this - * shortcut. - * - * Reason: Otherwise we should have running hashes for SHA512 and SHA224 - * in order to satisfy 'weird' needs from the server side. - */ - if( ssl->transform_negotiate->ciphersuite_info->mac == - MBEDTLS_MD_SHA384 ) - { - md_alg = MBEDTLS_MD_SHA384; - ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; - } - else - { - md_alg = MBEDTLS_MD_SHA256; - ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; - } - ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); - - /* Info from md_alg will be used instead */ - hashlen = 0; - offset = 2; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, - ssl->out_msg + 6 + offset, &n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); - return( ret ); - } - - ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); - ssl->out_msg[5 + offset] = (unsigned char)( n ); - - ssl->out_msglen = 6 + n + offset; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); - - return( ret ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) -{ - int ret; - uint32_t lifetime; - size_t ticket_len; - unsigned char *ticket; - const unsigned char *msg; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* - * struct { - * uint32 ticket_lifetime_hint; - * opaque ticket<0..2^16-1>; - * } NewSessionTicket; - * - * 0 . 3 ticket_lifetime_hint - * 4 . 5 ticket_len (n) - * 6 . 5+n ticket content - */ - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || - ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); - } - - msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - - lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) | - ( msg[2] << 8 ) | ( msg[3] ); - - ticket_len = ( msg[4] << 8 ) | ( msg[5] ); - - if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); - - /* We're not waiting for a NewSessionTicket message any more */ - ssl->handshake->new_session_ticket = 0; - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; - - /* - * Zero-length ticket means the server changed his mind and doesn't want - * to send a ticket after all, so just forget it - */ - if( ticket_len == 0 ) - return( 0 ); - - mbedtls_zeroize( ssl->session_negotiate->ticket, - ssl->session_negotiate->ticket_len ); - mbedtls_free( ssl->session_negotiate->ticket ); - ssl->session_negotiate->ticket = NULL; - ssl->session_negotiate->ticket_len = 0; - - if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - memcpy( ticket, msg + 6, ticket_len ); - - ssl->session_negotiate->ticket = ticket; - ssl->session_negotiate->ticket_len = ticket_len; - ssl->session_negotiate->ticket_lifetime = lifetime; - - /* - * RFC 5077 section 3.4: - * "If the client receives a session ticket from the server, then it - * discards any Session ID that was sent in the ServerHello." - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); - ssl->session_negotiate->id_len = 0; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -/* - * SSL handshake -- client side -- single step - */ -int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); - - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - return( ret ); - } -#endif - - /* Change state now, so that it is right in mbedtls_ssl_read_record(), used - * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && - ssl->handshake->new_session_ticket != 0 ) - { - ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; - } -#endif - - switch( ssl->state ) - { - case MBEDTLS_SSL_HELLO_REQUEST: - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; - break; - - /* - * ==> ClientHello - */ - case MBEDTLS_SSL_CLIENT_HELLO: - ret = ssl_write_client_hello( ssl ); - break; - - /* - * <== ServerHello - * Certificate - * ( ServerKeyExchange ) - * ( CertificateRequest ) - * ServerHelloDone - */ - case MBEDTLS_SSL_SERVER_HELLO: - ret = ssl_parse_server_hello( ssl ); - break; - - case MBEDTLS_SSL_SERVER_CERTIFICATE: - ret = mbedtls_ssl_parse_certificate( ssl ); - break; - - case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: - ret = ssl_parse_server_key_exchange( ssl ); - break; - - case MBEDTLS_SSL_CERTIFICATE_REQUEST: - ret = ssl_parse_certificate_request( ssl ); - break; - - case MBEDTLS_SSL_SERVER_HELLO_DONE: - ret = ssl_parse_server_hello_done( ssl ); - break; - - /* - * ==> ( Certificate/Alert ) - * ClientKeyExchange - * ( CertificateVerify ) - * ChangeCipherSpec - * Finished - */ - case MBEDTLS_SSL_CLIENT_CERTIFICATE: - ret = mbedtls_ssl_write_certificate( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: - ret = ssl_write_client_key_exchange( ssl ); - break; - - case MBEDTLS_SSL_CERTIFICATE_VERIFY: - ret = ssl_write_certificate_verify( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: - ret = mbedtls_ssl_write_change_cipher_spec( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_FINISHED: - ret = mbedtls_ssl_write_finished( ssl ); - break; - - /* - * <== ( NewSessionTicket ) - * ChangeCipherSpec - * Finished - */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: - ret = ssl_parse_new_session_ticket( ssl ); - break; -#endif - - case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: - ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); - break; - - case MBEDTLS_SSL_SERVER_FINISHED: - ret = mbedtls_ssl_parse_finished( ssl ); - break; - - case MBEDTLS_SSL_FLUSH_BUFFERS: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; - break; - - case MBEDTLS_SSL_HANDSHAKE_WRAPUP: - mbedtls_ssl_handshake_wrapup( ssl ); - break; - - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - return( ret ); -} -#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/components/security/mbedtls/src/ssl_cookie.c b/components/security/mbedtls/src/ssl_cookie.c deleted file mode 100644 index caf11999..00000000 --- a/components/security/mbedtls/src/ssl_cookie.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * DTLS cookie callbacks implementation - * - * 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) - */ -/* - * These session callbacks use a simple chained list - * to store and retrieve the session information. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_COOKIE_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/ssl_cookie.h" -#include "mbedtls/ssl_internal.h" - -#include - -/* 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; -} - -/* - * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is - * available. Try SHA-256 first, 512 wastes resources since we need to stay - * with max 32 bytes of cookie for DTLS 1.0 - */ -#if defined(MBEDTLS_SHA256_C) -#define COOKIE_MD MBEDTLS_MD_SHA224 -#define COOKIE_MD_OUTLEN 32 -#define COOKIE_HMAC_LEN 28 -#elif defined(MBEDTLS_SHA512_C) -#define COOKIE_MD MBEDTLS_MD_SHA384 -#define COOKIE_MD_OUTLEN 48 -#define COOKIE_HMAC_LEN 28 -#elif defined(MBEDTLS_SHA1_C) -#define COOKIE_MD MBEDTLS_MD_SHA1 -#define COOKIE_MD_OUTLEN 20 -#define COOKIE_HMAC_LEN 20 -#else -#error "DTLS hello verify needs SHA-1 or SHA-2" -#endif - -/* - * Cookies are formed of a 4-bytes timestamp (or serial number) and - * an HMAC of timestemp and client ID. - */ -#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) - -void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) -{ - mbedtls_md_init( &ctx->hmac_ctx ); -#if !defined(MBEDTLS_HAVE_TIME) - ctx->serial = 0; -#endif - ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) -{ - ctx->timeout = delay; -} - -void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) -{ - mbedtls_md_free( &ctx->hmac_ctx ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - - mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); -} - -int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char key[COOKIE_MD_OUTLEN]; - - if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) - return( ret ); - - ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); - if( ret != 0 ) - return( ret ); - - ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); - if( ret != 0 ) - return( ret ); - - mbedtls_zeroize( key, sizeof( key ) ); - - return( 0 ); -} - -/* - * Generate the HMAC part of a cookie - */ -static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, - const unsigned char time[4], - unsigned char **p, unsigned char *end, - const unsigned char *cli_id, size_t cli_id_len ) -{ - unsigned char hmac_out[COOKIE_MD_OUTLEN]; - - if( (size_t)( end - *p ) < COOKIE_HMAC_LEN ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || - mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || - mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || - mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) - { - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); - *p += COOKIE_HMAC_LEN; - - return( 0 ); -} - -/* - * Generate cookie for DTLS ClientHello verification - */ -int mbedtls_ssl_cookie_write( void *p_ctx, - unsigned char **p, unsigned char *end, - const unsigned char *cli_id, size_t cli_id_len ) -{ - int ret; - mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; - unsigned long t; - - if( ctx == NULL || cli_id == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( (size_t)( end - *p ) < COOKIE_LEN ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - -#if defined(MBEDTLS_HAVE_TIME) - t = (unsigned long) mbedtls_time( NULL ); -#else - t = ctx->serial++; -#endif - - (*p)[0] = (unsigned char)( t >> 24 ); - (*p)[1] = (unsigned char)( t >> 16 ); - (*p)[2] = (unsigned char)( t >> 8 ); - (*p)[3] = (unsigned char)( t ); - *p += 4; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); -#endif - - ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, - p, end, cli_id, cli_id_len ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + - MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Check a cookie - */ -int mbedtls_ssl_cookie_check( void *p_ctx, - const unsigned char *cookie, size_t cookie_len, - const unsigned char *cli_id, size_t cli_id_len ) -{ - unsigned char ref_hmac[COOKIE_HMAC_LEN]; - int ret = 0; - unsigned char *p = ref_hmac; - mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; - unsigned long cur_time, cookie_time; - - if( ctx == NULL || cli_id == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( cookie_len != COOKIE_LEN ) - return( -1 ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); -#endif - - if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, - &p, p + sizeof( ref_hmac ), - cli_id, cli_id_len ) != 0 ) - ret = -1; - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + - MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - if( ret != 0 ) - return( ret ); - - if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) - return( -1 ); - -#if defined(MBEDTLS_HAVE_TIME) - cur_time = (unsigned long) mbedtls_time( NULL ); -#else - cur_time = ctx->serial; -#endif - - cookie_time = ( (unsigned long) cookie[0] << 24 ) | - ( (unsigned long) cookie[1] << 16 ) | - ( (unsigned long) cookie[2] << 8 ) | - ( (unsigned long) cookie[3] ); - - if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) - return( -1 ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/components/security/mbedtls/src/ssl_srv.c b/components/security/mbedtls/src/ssl_srv.c deleted file mode 100644 index fc0d2d7b..00000000 --- a/components/security/mbedtls/src/ssl_srv.c +++ /dev/null @@ -1,3926 +0,0 @@ -/* - * SSLv3/TLSv1 server-side 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_SSL_SRV_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" - -#include - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -/* 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_SSL_DTLS_HELLO_VERIFY) -int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, - const unsigned char *info, - size_t ilen ) -{ - if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - mbedtls_free( ssl->cli_id ); - - if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( ssl->cli_id, info, ilen ); - ssl->cli_id_len = ilen; - - return( 0 ); -} - -void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie ) -{ - conf->f_cookie_write = f_cookie_write; - conf->f_cookie_check = f_cookie_check; - conf->p_cookie = p_cookie; -} -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - int ret; - size_t servername_list_size, hostname_len; - const unsigned char *p; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); - - servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); - if( servername_list_size + 2 != len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - p = buf + 2; - while( servername_list_size > 0 ) - { - hostname_len = ( ( p[1] << 8 ) | p[2] ); - if( hostname_len + 3 > servername_list_size ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) - { - ret = ssl->conf->f_sni( ssl->conf->p_sni, - ssl, p + 3, hostname_len ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - return( 0 ); - } - - servername_list_size -= hostname_len + 3; - p += hostname_len + 3; - } - - if( servername_list_size != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - int ret; - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - /* Check verify-data in constant-time. The length OTOH is no secret */ - if( len != 1 + ssl->verify_data_len || - buf[0] != ssl->verify_data_len || - mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data, - ssl->verify_data_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - } - else -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - { - if( len != 1 || buf[0] != 0x0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - } - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - size_t sig_alg_list_size; - const unsigned char *p; - const unsigned char *end = buf + len; - const int *md_cur; - - - sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); - if( sig_alg_list_size + 2 != len || - sig_alg_list_size % 2 != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* - * For now, ignore the SignatureAlgorithm part and rely on offered - * ciphersuites only for that part. To be fixed later. - * - * So, just look at the HashAlgorithm part. - */ - for( md_cur = ssl->conf->sig_hashes; *md_cur != MBEDTLS_MD_NONE; md_cur++ ) { - for( p = buf + 2; p < end; p += 2 ) { - if( *md_cur == (int) mbedtls_ssl_md_alg_from_hash( p[0] ) ) { - ssl->handshake->sig_alg = p[0]; - goto have_sig_alg; - } - } - } - - /* Some key echanges do not need signatures at all */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no signature_algorithm in common" ) ); - return( 0 ); - -have_sig_alg: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", - ssl->handshake->sig_alg ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - size_t list_size, our_size; - const unsigned char *p; - const mbedtls_ecp_curve_info *curve_info, **curves; - - list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); - if( list_size + 2 != len || - list_size % 2 != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* Should never happen unless client duplicates the extension */ - if( ssl->handshake->curves != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* Don't allow our peer to make us allocate too much memory, - * and leave room for a final 0 */ - our_size = list_size / 2 + 1; - if( our_size > MBEDTLS_ECP_DP_MAX ) - our_size = MBEDTLS_ECP_DP_MAX; - - if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - ssl->handshake->curves = curves; - - p = buf + 2; - while( list_size > 0 && our_size > 1 ) - { - curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); - - if( curve_info != NULL ) - { - *curves++ = curve_info; - our_size--; - } - - list_size -= 2; - p += 2; - } - - return( 0 ); -} - -static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - size_t list_size; - const unsigned char *p; - - list_size = buf[0]; - if( list_size + 1 != len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - p = buf + 1; - while( list_size > 0 ) - { - if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || - p[0] == MBEDTLS_ECP_PF_COMPRESSED ) - { -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) - ssl->handshake->ecdh_ctx.point_format = p[0]; -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl->handshake->ecjpake_ctx.point_format = p[0]; -#endif - MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); - return( 0 ); - } - - list_size--; - p++; - } - - return( 0 ); -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - int ret; - - if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); - return( 0 ); - } - - if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, - buf, len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); - return( ret ); - } - - /* Only mark the extension as OK when we're sure it is */ - ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->session_negotiate->mfl_code = buf[0]; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ((void) buf); - - if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) - ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ((void) buf); - - if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ((void) buf); - - if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t len ) -{ - int ret; - mbedtls_ssl_session session; - - mbedtls_ssl_session_init( &session ); - - if( ssl->conf->f_ticket_parse == NULL || - ssl->conf->f_ticket_write == NULL ) - { - return( 0 ); - } - - /* Remember the client asked us to send a new ticket */ - ssl->handshake->new_session_ticket = 1; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); - - if( len == 0 ) - return( 0 ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); - return( 0 ); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - /* - * Failures are ok: just ignore the ticket and proceed. - */ - if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, - buf, len ) ) != 0 ) - { - mbedtls_ssl_session_free( &session ); - - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); - else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); - else - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); - - return( 0 ); - } - - /* - * Keep the session ID sent by the client, since we MUST send it back to - * inform them we're accepting the ticket (RFC 5077 section 3.4) - */ - session.id_len = ssl->session_negotiate->id_len; - memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); - - mbedtls_ssl_session_free( ssl->session_negotiate ); - memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); - - /* Zeroize instead of free as we copied the content */ - mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); - - ssl->handshake->resume = 1; - - /* Don't send a new ticket after all, this one is OK */ - ssl->handshake->new_session_ticket = 0; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_ALPN) -static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - size_t list_len, cur_len, ours_len; - const unsigned char *theirs, *start, *end; - const char **ours; - - /* If ALPN not configured, just ignore the extension */ - if( ssl->conf->alpn_list == NULL ) - return( 0 ); - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - */ - - /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ - if( len < 4 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - list_len = ( buf[0] << 8 ) | buf[1]; - if( list_len != len - 2 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - /* - * Use our order of preference - */ - start = buf + 2; - end = buf + len; - for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) - { - ours_len = strlen( *ours ); - for( theirs = start; theirs != end; theirs += cur_len ) - { - /* If the list is well formed, we should get equality first */ - if( theirs > end ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - cur_len = *theirs++; - - /* Empty strings MUST NOT be included */ - if( cur_len == 0 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - if( cur_len == ours_len && - memcmp( theirs, *ours, cur_len ) == 0 ) - { - ssl->alpn_chosen = *ours; - return( 0 ); - } - } - } - - /* If we get there, no match was found */ - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); -} -#endif /* MBEDTLS_SSL_ALPN */ - -/* - * Auxiliary functions for ServerHello parsing and related actions - */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/* - * Return 0 if the given key uses one of the acceptable curves, -1 otherwise - */ -#if defined(MBEDTLS_ECDSA_C) -static int ssl_check_key_curve( mbedtls_pk_context *pk, - const mbedtls_ecp_curve_info **curves ) -{ - const mbedtls_ecp_curve_info **crv = curves; - mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; - - while( *crv != NULL ) - { - if( (*crv)->grp_id == grp_id ) - return( 0 ); - crv++; - } - - return( -1 ); -} -#endif /* MBEDTLS_ECDSA_C */ - -/* - * Try picking a certificate for this ciphersuite, - * return 0 on success and -1 on failure. - */ -static int ssl_pick_cert( mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) -{ - mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; - mbedtls_pk_type_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); - uint32_t flags; - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_key_cert != NULL ) - list = ssl->handshake->sni_key_cert; - else -#endif - list = ssl->conf->key_cert; - - if( pk_alg == MBEDTLS_PK_NONE ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); - - if( list == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); - return( -1 ); - } - - for( cur = list; cur != NULL; cur = cur->next ) - { - MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", - cur->cert ); - - if( ! mbedtls_pk_can_do( cur->key, pk_alg ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); - continue; - } - - /* - * This avoids sending the client a cert it'll reject based on - * keyUsage or other extensions. - * - * It also allows the user to provision different certificates for - * different uses based on keyUsage, eg if they want to avoid signing - * and decrypting with the same RSA key. - */ - if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, - MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " - "(extended) key usage extension" ) ); - continue; - } - -#if defined(MBEDTLS_ECDSA_C) - if( pk_alg == MBEDTLS_PK_ECDSA && - ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); - continue; - } -#endif - - /* - * Try to select a SHA-1 certificate for pre-1.2 clients, but still - * present them a SHA-higher cert rather than failing if it's the only - * one we got that satisfies the other conditions. - */ - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && - cur->cert->sig_md != MBEDTLS_MD_SHA1 ) - { - if( fallback == NULL ) - fallback = cur; - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " - "sha-2 with pre-TLS 1.2 client" ) ); - continue; - } - } - - /* If we get there, we got a winner */ - break; - } - - if( cur == NULL ) - cur = fallback; - - /* Do not update ssl->handshake->key_cert unless there is a match */ - if( cur != NULL ) - { - ssl->handshake->key_cert = cur; - MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", - ssl->handshake->key_cert->cert ); - return( 0 ); - } - - return( -1 ); -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/* - * Check if a given ciphersuite is suitable for use with our config/keys/etc - * Sets ciphersuite_info only if the suite matches. - */ -static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, - const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) -{ - const mbedtls_ssl_ciphersuite_t *suite_info; - - suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); - if( suite_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) ); - - if( suite_info->min_minor_ver > ssl->minor_ver || - suite_info->max_minor_ver < ssl->minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); - return( 0 ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) - return( 0 ); -#endif - -#if defined(MBEDTLS_ARC4_C) - if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); - return( 0 ); - } -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && - ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " - "not configured or ext missing" ) ); - return( 0 ); - } -#endif - - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) - if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && - ( ssl->handshake->curves == NULL || - ssl->handshake->curves[0] == NULL ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " - "no common elliptic curve" ) ); - return( 0 ); - } -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - /* If the ciphersuite requires a pre-shared key and we don't - * have one, skip it now rather than failing later */ - if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && - ssl->conf->f_psk == NULL && - ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || - ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); - return( 0 ); - } -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - /* - * Final check: if ciphersuite requires us to have a - * certificate/key of a particular type: - * - select the appropriate certificate if we have one, or - * - try the next ciphersuite if we don't - * This must be done last since we modify the key_cert list. - */ - if( ssl_pick_cert( ssl, suite_info ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " - "no suitable certificate" ) ); - return( 0 ); - } -#endif - - *ciphersuite_info = suite_info; - return( 0 ); -} - -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) -static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) -{ - int ret, got_common_suite; - unsigned int i, j; - size_t n; - unsigned int ciph_len, sess_len, chal_len; - unsigned char *buf, *p; - const int *ciphersuites; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - buf = ssl->in_hdr; - - MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", - buf[2] ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", - ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", - buf[3], buf[4] ) ); - - /* - * SSLv2 Client Hello - * - * Record layer: - * 0 . 1 message length - * - * SSL layer: - * 2 . 2 message type - * 3 . 4 protocol version - */ - if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || - buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; - - if( n < 17 || n > 512 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) - ? buf[4] : ssl->conf->max_minor_ver; - - if( ssl->minor_ver < ssl->conf->min_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" - " [%d:%d] < [%d:%d]", - ssl->major_ver, ssl->minor_ver, - ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); - } - - ssl->handshake->max_major_ver = buf[3]; - ssl->handshake->max_minor_ver = buf[4]; - - if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - ssl->handshake->update_checksum( ssl, buf + 2, n ); - - buf = ssl->in_msg; - n = ssl->in_left - 5; - - /* - * 0 . 1 ciphersuitelist length - * 2 . 3 session id length - * 4 . 5 challenge length - * 6 . .. ciphersuitelist - * .. . .. session id - * .. . .. challenge - */ - MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); - - ciph_len = ( buf[0] << 8 ) | buf[1]; - sess_len = ( buf[2] << 8 ) | buf[3]; - chal_len = ( buf[4] << 8 ) | buf[5]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", - ciph_len, sess_len, chal_len ) ); - - /* - * Make sure each parameter length is valid - */ - if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( sess_len > 32 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( chal_len < 8 || chal_len > 32 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( n != 6 + ciph_len + sess_len + chal_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", - buf + 6, ciph_len ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", - buf + 6 + ciph_len, sess_len ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", - buf + 6 + ciph_len + sess_len, chal_len ); - - p = buf + 6 + ciph_len; - ssl->session_negotiate->id_len = sess_len; - memset( ssl->session_negotiate->id, 0, - sizeof( ssl->session_negotiate->id ) ); - memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); - - p += sess_len; - memset( ssl->handshake->randbytes, 0, 64 ); - memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); - - /* - * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV - */ - for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) - { - if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " - "during renegotiation" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - break; - } - } - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) - { - if( p[0] == 0 && - p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && - p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); - - if( ssl->minor_ver < ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - break; - } - } -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ - - got_common_suite = 0; - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; - ciphersuite_info = NULL; -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) - { - for( i = 0; ciphersuites[i] != 0; i++ ) -#else - for( i = 0; ciphersuites[i] != 0; i++ ) - { - for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) -#endif - { - if( p[0] != 0 || - p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || - p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) - continue; - - got_common_suite = 1; - - if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], - &ciphersuite_info ) ) != 0 ) - return( ret ); - - if( ciphersuite_info != NULL ) - goto have_ciphersuite_v2; - } - } - - if( got_common_suite ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " - "but none of them usable" ) ); - return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); - } - -have_ciphersuite_v2: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); - - ssl->session_negotiate->ciphersuite = ciphersuites[i]; - ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; - - /* - * SSLv2 Client Hello relevant renegotiation security checks - */ - if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->in_left = 0; - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ - -static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) -{ - int ret, got_common_suite; - size_t i, j; - size_t ciph_offset, comp_offset, ext_offset; - size_t msg_len, ciph_len, sess_len, comp_len, ext_len; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - size_t cookie_offset, cookie_len; -#endif - unsigned char *buf, *p, *ext; -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renegotiation_info_seen = 0; -#endif - int handshake_failure = 0; - const int *ciphersuites; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - int major, minor; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -read_record_header: -#endif - /* - * If renegotiating, then the input was read with mbedtls_ssl_read_record(), - * otherwise read it ourselves manually in order to support SSLv2 - * ClientHello, which doesn't use the same record layer format. - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) -#endif - { - if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - } - - buf = ssl->in_hdr; - -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) -#endif - if( ( buf[0] & 0x80 ) != 0 ) - return ssl_parse_client_hello_v2( ssl ); -#endif - - MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); - - /* - * SSLv3/TLS Client Hello - * - * Record layer: - * 0 . 0 message type - * 1 . 2 protocol version - * 3 . 11 DTLS: epoch + record sequence number - * 3 . 4 message length - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", - buf[0] ) ); - - if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", - ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", - buf[1], buf[2] ) ); - - mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); - - /* According to RFC 5246 Appendix E.1, the version here is typically - * "{03,00}, the lowest version number supported by the client, [or] the - * value of ClientHello.client_version", so the only meaningful check here - * is the major version shouldn't be less than 3 */ - if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* For DTLS if this is the initial handshake, remember the client sequence - * number to use it in our next message (RFC 6347 4.2.1) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE -#endif - ) - { - /* Epoch should be 0 for initial handshakes */ - if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 ); - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); - ssl->next_record_offset = 0; - ssl->in_left = 0; - goto read_record_header; - } - - /* No MAC to check yet, so we can update right now */ - mbedtls_ssl_dtls_replay_update( ssl ); -#endif - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - /* Set by mbedtls_ssl_read_record() */ - msg_len = ssl->in_hslen; - } - else -#endif - { - if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - /* Done reading this record, get ready for the next one */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl ); - else -#endif - ssl->in_left = 0; - } - - buf = ssl->in_msg; - - MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); - - ssl->handshake->update_checksum( ssl, buf, msg_len ); - - /* - * Handshake layer: - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 DTLS only: message seqence number - * 6 . 8 DTLS only: fragment offset - * 9 . 11 DTLS only: fragment length - */ - if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); - - if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", - ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); - - /* We don't support fragmentation of ClientHello (yet?) */ - if( buf[1] != 0 || - msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* - * Copy the client's handshake message_seq on initial handshakes, - * check sequence number on renego. - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - /* This couldn't be done in ssl_prepare_handshake_record() */ - unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | - ssl->in_msg[5]; - - if( cli_msg_seq != ssl->handshake->in_msg_seq ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " - "%d (expected %d)", cli_msg_seq, - ssl->handshake->in_msg_seq ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->handshake->in_msg_seq++; - } - else -#endif - { - unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | - ssl->in_msg[5]; - ssl->handshake->out_msg_seq = cli_msg_seq; - ssl->handshake->in_msg_seq = cli_msg_seq + 1; - } - - /* - * For now we don't support fragmentation, so make sure - * fragment_offset == 0 and fragment_length == length - */ - if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || - memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - buf += mbedtls_ssl_hs_hdr_len( ssl ); - msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); - - /* - * ClientHello layer: - * 0 . 1 protocol version - * 2 . 33 random bytes (starting with 4 bytes of Unix time) - * 34 . 35 session id length (1 byte) - * 35 . 34+x session id - * 35+x . 35+x DTLS only: cookie length (1 byte) - * 36+x . .. DTLS only: cookie - * .. . .. ciphersuite list length (2 bytes) - * .. . .. ciphersuite list - * .. . .. compression alg. list length (1 byte) - * .. . .. compression alg. list - * .. . .. extensions length (2 bytes, optional) - * .. . .. extensions (optional) - */ - - /* - * Minimal length (with everything empty and extensions ommitted) is - * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can - * read at least up to session id length without worrying. - */ - if( msg_len < 38 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* - * Check and save the protocol version - */ - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); - - mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, - ssl->conf->transport, buf ); - - ssl->handshake->max_major_ver = ssl->major_ver; - ssl->handshake->max_minor_ver = ssl->minor_ver; - - if( ssl->major_ver < ssl->conf->min_major_ver || - ssl->minor_ver < ssl->conf->min_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" - " [%d:%d] < [%d:%d]", - ssl->major_ver, ssl->minor_ver, - ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); - } - - if( ssl->major_ver > ssl->conf->max_major_ver ) - { - ssl->major_ver = ssl->conf->max_major_ver; - ssl->minor_ver = ssl->conf->max_minor_ver; - } - else if( ssl->minor_ver > ssl->conf->max_minor_ver ) - ssl->minor_ver = ssl->conf->max_minor_ver; - - /* - * Save client random (inc. Unix time) - */ - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); - - memcpy( ssl->handshake->randbytes, buf + 2, 32 ); - - /* - * Check the session ID length and save session ID - */ - sess_len = buf[34]; - - if( sess_len > sizeof( ssl->session_negotiate->id ) || - sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); - - ssl->session_negotiate->id_len = sess_len; - memset( ssl->session_negotiate->id, 0, - sizeof( ssl->session_negotiate->id ) ); - memcpy( ssl->session_negotiate->id, buf + 35, - ssl->session_negotiate->id_len ); - - /* - * Check the cookie length and content - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - cookie_offset = 35 + sess_len; - cookie_len = buf[cookie_offset]; - - if( cookie_offset + 1 + cookie_len + 2 > msg_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", - buf + cookie_offset + 1, cookie_len ); - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) - if( ssl->conf->f_cookie_check != NULL -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE -#endif - ) - { - if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, - buf + cookie_offset + 1, cookie_len, - ssl->cli_id, ssl->cli_id_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); - ssl->handshake->verify_cookie_len = 1; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); - ssl->handshake->verify_cookie_len = 0; - } - } - else -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - { - /* We know we didn't send a cookie, so it should be empty */ - if( cookie_len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); - } - - /* - * Check the ciphersuitelist length (will be parsed later) - */ - ciph_offset = cookie_offset + 1 + cookie_len; - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - ciph_offset = 35 + sess_len; - - ciph_len = ( buf[ciph_offset + 0] << 8 ) - | ( buf[ciph_offset + 1] ); - - if( ciph_len < 2 || - ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ - ( ciph_len % 2 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", - buf + ciph_offset + 2, ciph_len ); - - /* - * Check the compression algorithms length and pick one - */ - comp_offset = ciph_offset + 2 + ciph_len; - - comp_len = buf[comp_offset]; - - if( comp_len < 1 || - comp_len > 16 || - comp_len + comp_offset + 1 > msg_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", - buf + comp_offset + 1, comp_len ); - - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; -#if defined(MBEDTLS_ZLIB_SUPPORT) - for( i = 0; i < comp_len; ++i ) - { - if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; - break; - } - } -#endif - - /* See comments in ssl_write_client_hello() */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; -#endif - - /* Do not parse the extensions if the protocol is SSLv3 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) - { -#endif - /* - * Check the extension length - */ - ext_offset = comp_offset + 1 + comp_len; - if( msg_len > ext_offset ) - { - if( msg_len < ext_offset + 2 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ext_len = ( buf[ext_offset + 0] << 8 ) - | ( buf[ext_offset + 1] ); - - if( ( ext_len > 0 && ext_len < 4 ) || - msg_len != ext_offset + 2 + ext_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - } - else - ext_len = 0; - - ext = buf + ext_offset + 2; - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); - - while( ext_len != 0 ) - { - unsigned int ext_id = ( ( ext[0] << 8 ) - | ( ext[1] ) ); - unsigned int ext_size = ( ( ext[2] << 8 ) - | ( ext[3] ) ); - - if( ext_size + 4 > ext_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - switch( ext_id ) - { -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - case MBEDTLS_TLS_EXT_SERVERNAME: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); - if( ssl->conf->f_sni == NULL ) - break; - - ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - - case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - renegotiation_info_seen = 1; -#endif - - ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - case MBEDTLS_TLS_EXT_SIG_ALG: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - break; -#endif - - ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); - - ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; - - case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); - ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; - - ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); - - ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); - - ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); - - ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); - - ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); - - ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_TLS_EXT_SESSION_TICKET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); - - ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_ALPN) - case MBEDTLS_TLS_EXT_ALPN: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); - - ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - - default: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", - ext_id ) ); - } - - ext_len -= 4 + ext_size; - ext += 4 + ext_size; - - if( ext_len > 0 && ext_len < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - } -#if defined(MBEDTLS_SSL_PROTO_SSL3) - } -#endif - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 ) - { - if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && - p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); - - if( ssl->minor_ver < ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - break; - } - } -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ - - /* - * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV - */ - for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) - { - if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } -#endif - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - break; - } - } - - /* - * Renegotiation security checks - */ - if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); - handshake_failure = 1; - } -#if defined(MBEDTLS_SSL_RENEGOTIATION) - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && - renegotiation_info_seen == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); - handshake_failure = 1; - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); - handshake_failure = 1; - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - renegotiation_info_seen == 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); - handshake_failure = 1; - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - if( handshake_failure == 1 ) - { - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* - * Search for a matching ciphersuite - * (At the end because we need information from the EC-based extensions - * and certificate from the SNI callback triggered by the SNI extension.) - */ - got_common_suite = 0; - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; - ciphersuite_info = NULL; -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) - { - for( i = 0; ciphersuites[i] != 0; i++ ) -#else - for( i = 0; ciphersuites[i] != 0; i++ ) - { - for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) -#endif - { - if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || - p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) - continue; - - got_common_suite = 1; - - if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], - &ciphersuite_info ) ) != 0 ) - return( ret ); - - if( ciphersuite_info != NULL ) - goto have_ciphersuite; - } - } - - if( got_common_suite ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " - "but none of them usable" ) ); - mbedtls_ssl_send_fatal_handshake_failure( ssl ); - return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - mbedtls_ssl_send_fatal_handshake_failure( ssl ); - return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); - } - -have_ciphersuite: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); - - ssl->session_negotiate->ciphersuite = ciphersuites[i]; - ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_recv_flight_completed( ssl ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const mbedtls_ssl_ciphersuite_t *suite = NULL; - const mbedtls_cipher_info_t *cipher = NULL; - - if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - *olen = 0; - return; - } - - /* - * RFC 7366: "If a server receives an encrypt-then-MAC request extension - * from a client and then selects a stream or Authenticated Encryption - * with Associated Data (AEAD) ciphersuite, it MUST NOT send an - * encrypt-then-MAC response extension back to the client." - */ - if( ( suite = mbedtls_ssl_ciphersuite_from_id( - ssl->session_negotiate->ciphersuite ) ) == NULL || - ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || - cipher->mode != MBEDTLS_MODE_CBC ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " - "extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->handshake->new_session_ticket == 0 ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - *p++ = 0x00; - *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; - *p++ = ssl->verify_data_len * 2 & 0xFF; - - memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); - p += ssl->verify_data_len; - memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); - p += ssl->verify_data_len; - } - else -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - { - *p++ = 0x00; - *p++ = 0x01; - *p++ = 0x00; - } - - *olen = p - buf; -} - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); - - *p++ = 0x00; - *p++ = 1; - - *p++ = ssl->session_negotiate->mfl_code; - - *olen = 5; -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - ((void) ssl); - - if( ( ssl->handshake->cli_exts & - MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); - - *p++ = 0x00; - *p++ = 2; - - *p++ = 1; - *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; - - *olen = 6; -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - int ret; - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t kkpp_len; - - *olen = 0; - - /* Skip costly computation if not needed */ - if( ssl->transform_negotiate->ciphersuite_info->key_exchange != - MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); - - if( end - p < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); - - ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, - p + 2, end - p - 2, &kkpp_len, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); - return; - } - - *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); - - *olen = kkpp_len + 4; -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_ALPN ) -static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - if( ssl->alpn_chosen == NULL ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); - - /* - * 0 . 1 ext identifier - * 2 . 3 ext length - * 4 . 5 protocol list length - * 6 . 6 protocol name length - * 7 . 7+n protocol name - */ - buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); - buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); - - *olen = 7 + strlen( ssl->alpn_chosen ); - - buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); - buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); - - buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); - buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); - - buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); - - memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) -static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *p = ssl->out_msg + 4; - unsigned char *cookie_len_byte; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); - - /* - * struct { - * ProtocolVersion server_version; - * opaque cookie<0..2^8-1>; - * } HelloVerifyRequest; - */ - - /* The RFC is not clear on this point, but sending the actual negotiated - * version looks like the most interoperable thing to do. */ - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, p ); - MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); - p += 2; - - /* If we get here, f_cookie_check is not null */ - if( ssl->conf->f_cookie_write == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* Skip length byte until we know the length */ - cookie_len_byte = p++; - - if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, - &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN, - ssl->cli_id, ssl->cli_id_len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); - return( ret ); - } - - *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); - - ssl->out_msglen = p - ssl->out_msg; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; - - ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - -static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t; -#endif - int ret; - size_t olen, ext_len = 0, n; - unsigned char *buf, *p; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->verify_cookie_len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); - - return( ssl_write_hello_verify_request( ssl ) ); - } -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - - if( ssl->conf->f_rng == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); - return( MBEDTLS_ERR_SSL_NO_RNG ); - } - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 protocol version - * 6 . 9 UNIX time() - * 10 . 37 random bytes - */ - buf = ssl->out_msg; - p = buf + 4; - - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, p ); - p += 2; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", - buf[4], buf[5] ) ); - -#if defined(MBEDTLS_HAVE_TIME) - t = mbedtls_time( NULL ); - *p++ = (unsigned char)( t >> 24 ); - *p++ = (unsigned char)( t >> 16 ); - *p++ = (unsigned char)( t >> 8 ); - *p++ = (unsigned char)( t ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); -#else - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) - return( ret ); - - p += 4; -#endif /* MBEDTLS_HAVE_TIME */ - - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) - return( ret ); - - p += 28; - - memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); - - /* - * Resume is 0 by default, see ssl_handshake_init(). - * It may be already set to 1 by ssl_parse_session_ticket_ext(). - * If not, try looking up session ID in our cache. - */ - if( ssl->handshake->resume == 0 && -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE && -#endif - ssl->session_negotiate->id_len != 0 && - ssl->conf->f_get_cache != NULL && - ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); - ssl->handshake->resume = 1; - } - - if( ssl->handshake->resume == 0 ) - { - /* - * New session, create a new session id, - * unless we're about to issue a session ticket - */ - ssl->state++; - -#if defined(MBEDTLS_HAVE_TIME) - ssl->session_negotiate->start = mbedtls_time( NULL ); -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - if( ssl->handshake->new_session_ticket != 0 ) - { - ssl->session_negotiate->id_len = n = 0; - memset( ssl->session_negotiate->id, 0, 32 ); - } - else -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - { - ssl->session_negotiate->id_len = n = 32; - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, - n ) ) != 0 ) - return( ret ); - } - } - else - { - /* - * Resuming a session - */ - n = ssl->session_negotiate->id_len; - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - } - - /* - * 38 . 38 session id length - * 39 . 38+n session id - * 39+n . 40+n chosen ciphersuite - * 41+n . 41+n chosen compression alg. - * 42+n . 43+n extensions length - * 44+n . 43+n+m extensions - */ - *p++ = (unsigned char) ssl->session_negotiate->id_len; - memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); - p += ssl->session_negotiate->id_len; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", - ssl->handshake->resume ? "a" : "no" ) ); - - *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); - *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); - *p++ = (unsigned char)( ssl->session_negotiate->compression ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", - mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", - ssl->session_negotiate->compression ) ); - - /* Do not write the extensions if the protocol is SSLv3 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) - { -#endif - - /* - * First write extensions, then the total length - */ - ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ALPN) - ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); - - if( ext_len > 0 ) - { - *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ext_len ) & 0xFF ); - p += ext_len; - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - } -#endif - - ssl->out_msglen = p - buf; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; - - ret = mbedtls_ssl_write_record( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); - - return( ret ); -} - -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else -static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - size_t dn_size, total_dn_size; /* excluding length bytes */ - size_t ct_len, sa_len; /* including length bytes */ - unsigned char *buf, *p; - const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - const mbedtls_x509_crt *crt; - int authmode; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); - - ssl->state++; - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) - authmode = ssl->handshake->sni_authmode; - else -#endif - authmode = ssl->conf->authmode; - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || - authmode == MBEDTLS_SSL_VERIFY_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); - return( 0 ); - } - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 4 cert type count - * 5 .. m-1 cert types - * m .. m+1 sig alg length (TLS 1.2 only) - * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) - * n .. n+1 length of all DNs - * n+2 .. n+3 length of DN 1 - * n+4 .. ... Distinguished Name #1 - * ... .. ... length of DN 2, etc. - */ - buf = ssl->out_msg; - p = buf + 4; - - /* - * Supported certificate types - * - * ClientCertificateType certificate_types<1..2^8-1>; - * enum { (255) } ClientCertificateType; - */ - ct_len = 0; - -#if defined(MBEDTLS_RSA_C) - p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; -#endif -#if defined(MBEDTLS_ECDSA_C) - p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; -#endif - - p[0] = (unsigned char) ct_len++; - p += ct_len; - - sa_len = 0; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * Add signature_algorithms for verify (TLS 1.2) - * - * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - * - * enum { (255) } HashAlgorithm; - * enum { (255) } SignatureAlgorithm; - */ - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - const int *cur; - - /* - * Supported signature algorithms - */ - for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) - { - unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); - - if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) - continue; - -#if defined(MBEDTLS_RSA_C) - p[2 + sa_len++] = hash; - p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; -#endif -#if defined(MBEDTLS_ECDSA_C) - p[2 + sa_len++] = hash; - p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; -#endif - } - - p[0] = (unsigned char)( sa_len >> 8 ); - p[1] = (unsigned char)( sa_len ); - sa_len += 2; - p += sa_len; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - /* - * DistinguishedName certificate_authorities<0..2^16-1>; - * opaque DistinguishedName<1..2^16-1>; - */ - p += 2; -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_ca_chain != NULL ) - crt = ssl->handshake->sni_ca_chain; - else -#endif - crt = ssl->conf->ca_chain; - - total_dn_size = 0; - while( crt != NULL && crt->version != 0 ) - { - dn_size = crt->subject_raw.len; - - if( end < p || - (size_t)( end - p ) < dn_size || - (size_t)( end - p ) < 2 + dn_size ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); - break; - } - - *p++ = (unsigned char)( dn_size >> 8 ); - *p++ = (unsigned char)( dn_size ); - memcpy( p, crt->subject_raw.p, dn_size ); - p += dn_size; - - MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); - - total_dn_size += 2 + dn_size; - crt = crt->next; - } - - ssl->out_msglen = p - buf; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; - ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); - ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); - - ret = mbedtls_ssl_write_record( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); - - return( ret ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) -{ - int ret; - - if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); - return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); - } - - if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, - mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), - MBEDTLS_ECDH_OURS ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t n = 0; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - unsigned char *p = ssl->out_msg + 4; - unsigned char *dig_signed = p; - size_t dig_signed_len = 0, len; - ((void) dig_signed); - ((void) dig_signed_len); - ((void) len); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); - ssl->state++; - return( 0 ); - } -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) - { - ssl_get_ecdh_params_from_cert( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); - ssl->state++; - return( 0 ); - } -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - size_t jlen; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p, &jlen, ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); - return( ret ); - } - - p += jlen; - n += jlen; - } -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - /* Note: we don't support identity hints, until someone asks - * for them. */ - *(p++) = 0x00; - *(p++) = 0x00; - - n += 2; - } -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * Ephemeral DH parameters: - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - if( ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->conf->dhm_P ) ) != 0 || - ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->conf->dhm_G ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_mpi_copy", ret ); - return( ret ); - } - - if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); - return( ret ); - } - - dig_signed = p; - dig_signed_len = len; - - p += len; - n += len; - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); - } -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - /* - * Ephemeral ECDH parameters: - * - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; - */ - const mbedtls_ecp_curve_info **curve = NULL; - const mbedtls_ecp_group_id *gid; - - /* Match our preference list against the offered curves */ - for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) - for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) - if( (*curve)->grp_id == *gid ) - goto curve_matching_done; - -curve_matching_done: - if( curve == NULL || *curve == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); - return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); - - if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, - (*curve)->grp_id ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); - return( ret ); - } - - if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, - p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); - return( ret ); - } - - dig_signed = p; - dig_signed_len = len; - - p += len; - n += len; - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) - { - size_t signature_len = 0; - unsigned int hashlen = 0; - unsigned char hash[64]; - mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; - - /* - * Choose hash algorithm. NONE means MD5 + SHA1 here. - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - md_alg = mbedtls_ssl_md_alg_from_hash( ssl->handshake->sig_alg ); - - if( md_alg == MBEDTLS_MD_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ciphersuite_info->key_exchange == - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) - { - md_alg = MBEDTLS_MD_SHA1; - } - else -#endif - { - md_alg = MBEDTLS_MD_NONE; - } - - /* - * Compute the hash to be signed - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( md_alg == MBEDTLS_MD_NONE ) - { - mbedtls_md5_context mbedtls_md5; - mbedtls_sha1_context mbedtls_sha1; - - mbedtls_md5_init( &mbedtls_md5 ); - mbedtls_sha1_init( &mbedtls_sha1 ); - - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); - */ - mbedtls_md5_starts( &mbedtls_md5 ); - mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); - mbedtls_md5_update( &mbedtls_md5, dig_signed, dig_signed_len ); - mbedtls_md5_finish( &mbedtls_md5, hash ); - - mbedtls_sha1_starts( &mbedtls_sha1 ); - mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); - mbedtls_sha1_update( &mbedtls_sha1, dig_signed, dig_signed_len ); - mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); - - hashlen = 36; - - mbedtls_md5_free( &mbedtls_md5 ); - mbedtls_sha1_free( &mbedtls_sha1 ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( md_alg != MBEDTLS_MD_NONE ) - { - mbedtls_md_context_t ctx; - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); - - mbedtls_md_init( &ctx ); - - /* Info from md_alg will be used instead */ - hashlen = 0; - - /* - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * }; - */ - if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); - return( ret ); - } - - mbedtls_md_starts( &ctx ); - mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); - mbedtls_md_update( &ctx, dig_signed, dig_signed_len ); - mbedtls_md_finish( &ctx, hash ); - mbedtls_md_free( &ctx ); - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); - - /* - * Make the signature - */ - if( mbedtls_ssl_own_key( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - *(p++) = ssl->handshake->sig_alg; - *(p++) = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); - - n += 2; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, - p + 2 , &signature_len, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); - return( ret ); - } - - *(p++) = (unsigned char)( signature_len >> 8 ); - *(p++) = (unsigned char)( signature_len ); - n += 2; - - MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); - - n += signature_len; - } -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - - ssl->out_msglen = 4 + n; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); - - return( 0 ); -} - -static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); - - ssl->out_msglen = 4; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_send_flight_completed( ssl ); -#endif - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, - const unsigned char *end ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t n; - - /* - * Receive G^Y mod P, premaster = (G^Y)^X mod P - */ - if( *p + 2 > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - n = ( (*p)[0] << 8 ) | (*p)[1]; - *p += 2; - - if( *p + n > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); - } - - *p += n; - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, - const unsigned char *p, - const unsigned char *end, - size_t pms_offset ) -{ - int ret; - size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); - unsigned char *pms = ssl->handshake->premaster + pms_offset; - unsigned char ver[2]; - unsigned char fake_pms[48], peer_pms[48]; - unsigned char mask; - size_t i, peer_pmslen; - unsigned int diff; - - if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - - /* - * Decrypt the premaster using own private RSA key - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( *p++ != ( ( len >> 8 ) & 0xFF ) || - *p++ != ( ( len ) & 0xFF ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - } -#endif - - if( p + len != end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - mbedtls_ssl_write_version( ssl->handshake->max_major_ver, - ssl->handshake->max_minor_ver, - ssl->conf->transport, ver ); - - /* - * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding - * must not cause the connection to end immediately; instead, send a - * bad_record_mac later in the handshake. - * Also, avoid data-dependant branches here to protect against - * timing-based variants. - */ - ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); - if( ret != 0 ) - return( ret ); - - ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, - peer_pms, &peer_pmslen, - sizeof( peer_pms ), - ssl->conf->f_rng, ssl->conf->p_rng ); - - diff = (unsigned int) ret; - diff |= peer_pmslen ^ 48; - diff |= peer_pms[0] ^ ver[0]; - diff |= peer_pms[1] ^ ver[1]; - -#if defined(MBEDTLS_SSL_DEBUG_ALL) - if( diff != 0 ) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); -#endif - - if( sizeof( ssl->handshake->premaster ) < pms_offset || - sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - ssl->handshake->pmslen = 48; - - /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - - for( i = 0; i < ssl->handshake->pmslen; i++ ) - pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, - const unsigned char *end ) -{ - int ret = 0; - size_t n; - - if( ssl->conf->f_psk == NULL && - ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || - ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - - /* - * Receive client pre-shared key identity name - */ - if( *p + 2 > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - n = ( (*p)[0] << 8 ) | (*p)[1]; - *p += 2; - - if( n < 1 || n > 65535 || *p + n > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ssl->conf->f_psk != NULL ) - { - if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) - ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; - } - else - { - /* Identity is not a big secret since clients send it in the clear, - * but treat it carefully anyway, just in case */ - if( n != ssl->conf->psk_identity_len || - mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) - { - ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; - } - } - - if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) - { - MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 ) - { - return( ret ); - } - - return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); - } - - *p += n; - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) -{ - int ret; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - unsigned char *p, *end; - - ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - end = ssl->in_msg + ssl->in_hslen; - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) - { - if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); - return( ret ); - } - - if( p != end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, - ssl->handshake->premaster, - MBEDTLS_PREMASTER_SIZE, - &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) - { - if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, - p, end - p) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); - } - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); - - if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, - &ssl->handshake->pmslen, - ssl->handshake->premaster, - MBEDTLS_MPI_MAX_SIZE, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) - { - if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); - return( ret ); - } - - if( p != end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); - return( ret ); - } - - if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); - return( ret ); - } - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); - return( ret ); - } - if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); - return( ret ); - } - - if( p != end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); - return( ret ); - } - - if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, - p, end - p ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); - } - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) - { - if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, - ssl->handshake->premaster, 32, &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); - - return( 0 ); -} - -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else -static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, sig_len; - unsigned char hash[48]; - unsigned char *hash_start = hash; - size_t hashlen; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - mbedtls_pk_type_t pk_alg; -#endif - mbedtls_md_type_t md_alg; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || - ssl->session_negotiate->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - /* Read the message without adding it to the checksum */ - do { - - if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); - return( ret ); - } - - ret = mbedtls_ssl_handle_message_type( ssl ); - - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); - - if( 0 != ret ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); - return( ret ); - } - - ssl->state++; - - /* Process the message contents */ - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || - ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - i = mbedtls_ssl_hs_hdr_len( ssl ); - - /* - * struct { - * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only - * opaque signature<0..2^16-1>; - * } DigitallySigned; - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - { - md_alg = MBEDTLS_MD_NONE; - hashlen = 36; - - /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ - if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, - MBEDTLS_PK_ECDSA ) ) - { - hash_start += 16; - hashlen -= 16; - md_alg = MBEDTLS_MD_SHA1; - } - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - if( i + 2 > ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - /* - * Hash - */ - md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); - - if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" - " for verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - -#if !defined(MBEDTLS_MD_SHA1) - if( MBEDTLS_MD_SHA1 == md_alg ) - hash_start += 16; -#endif - - /* Info from md_alg will be used instead */ - hashlen = 0; - - i++; - - /* - * Signature - */ - if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) - == MBEDTLS_PK_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" - " for verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - /* - * Check the certificate's key type matches the signature alg - */ - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - i++; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( i + 2 > ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; - i += 2; - - if( i + sig_len != ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - /* Calculate hash and verify signature */ - ssl->handshake->calc_verify( ssl, hash ); - - if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, - md_alg, hash_start, hashlen, - ssl->in_msg + i, sig_len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); - return( ret ); - } - - mbedtls_ssl_update_handshake_status( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); - - return( ret ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t tlen; - uint32_t lifetime; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); - - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; - - /* - * struct { - * uint32 ticket_lifetime_hint; - * opaque ticket<0..2^16-1>; - * } NewSessionTicket; - * - * 4 . 7 ticket_lifetime_hint (0 = unspecified) - * 8 . 9 ticket_len (n) - * 10 . 9+n ticket content - */ - - if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, - ssl->session_negotiate, - ssl->out_msg + 10, - ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN, - &tlen, &lifetime ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); - tlen = 0; - } - - ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; - ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; - ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; - ssl->out_msg[7] = ( lifetime ) & 0xFF; - - ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); - ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); - - ssl->out_msglen = 10 + tlen; - - /* - * Morally equivalent to updating ssl->state, but NewSessionTicket and - * ChangeCipherSpec share the same state. - */ - ssl->handshake->new_session_ticket = 0; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -/* - * SSL handshake -- server side -- single step - */ -int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); - - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - return( ret ); - } -#endif - - switch( ssl->state ) - { - case MBEDTLS_SSL_HELLO_REQUEST: - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; - break; - - /* - * <== ClientHello - */ - case MBEDTLS_SSL_CLIENT_HELLO: - ret = ssl_parse_client_hello( ssl ); - break; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: - return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); -#endif - - /* - * ==> ServerHello - * Certificate - * ( ServerKeyExchange ) - * ( CertificateRequest ) - * ServerHelloDone - */ - case MBEDTLS_SSL_SERVER_HELLO: - ret = ssl_write_server_hello( ssl ); - break; - - case MBEDTLS_SSL_SERVER_CERTIFICATE: - ret = mbedtls_ssl_write_certificate( ssl ); - break; - - case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: - ret = ssl_write_server_key_exchange( ssl ); - break; - - case MBEDTLS_SSL_CERTIFICATE_REQUEST: - ret = ssl_write_certificate_request( ssl ); - break; - - case MBEDTLS_SSL_SERVER_HELLO_DONE: - ret = ssl_write_server_hello_done( ssl ); - break; - - /* - * <== ( Certificate/Alert ) - * ClientKeyExchange - * ( CertificateVerify ) - * ChangeCipherSpec - * Finished - */ - case MBEDTLS_SSL_CLIENT_CERTIFICATE: - ret = mbedtls_ssl_parse_certificate( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: - ret = ssl_parse_client_key_exchange( ssl ); - break; - - case MBEDTLS_SSL_CERTIFICATE_VERIFY: - ret = ssl_parse_certificate_verify( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: - ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_FINISHED: - ret = mbedtls_ssl_parse_finished( ssl ); - break; - - /* - * ==> ( NewSessionTicket ) - * ChangeCipherSpec - * Finished - */ - case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - if( ssl->handshake->new_session_ticket != 0 ) - ret = ssl_write_new_session_ticket( ssl ); - else -#endif - ret = mbedtls_ssl_write_change_cipher_spec( ssl ); - break; - - case MBEDTLS_SSL_SERVER_FINISHED: - ret = mbedtls_ssl_write_finished( ssl ); - break; - - case MBEDTLS_SSL_FLUSH_BUFFERS: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; - break; - - case MBEDTLS_SSL_HANDSHAKE_WRAPUP: - mbedtls_ssl_handshake_wrapup( ssl ); - break; - - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - return( ret ); -} -#endif /* MBEDTLS_SSL_SRV_C */ diff --git a/components/security/mbedtls/src/ssl_ticket.c b/components/security/mbedtls/src/ssl_ticket.c deleted file mode 100644 index 4d9116d2..00000000 --- a/components/security/mbedtls/src/ssl_ticket.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * TLS server tickets callbacks implementation - * - * 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_SSL_TICKET_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/ssl_ticket.h" - -#include - -/* 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; -} - -/* - * Initialze context - */ -void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -#define MAX_KEY_BYTES 32 /* 256 bits */ - -/* - * Generate/update a key - */ -static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, - unsigned char index ) -{ - int ret; - unsigned char buf[MAX_KEY_BYTES]; - mbedtls_ssl_ticket_key *key = ctx->keys + index; - -#if defined(MBEDTLS_HAVE_TIME) - key->generation_time = (uint32_t) mbedtls_time( NULL ); -#endif - - if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) - return( ret ); - - if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) - return( ret ); - - /* With GCM and CCM, same context can encrypt & decrypt */ - ret = mbedtls_cipher_setkey( &key->ctx, buf, - mbedtls_cipher_get_key_bitlen( &key->ctx ), - MBEDTLS_ENCRYPT ); - - mbedtls_zeroize( buf, sizeof( buf ) ); - - return( ret ); -} - -/* - * Rotate/generate keys if necessary - */ -static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) -{ -#if !defined(MBEDTLS_HAVE_TIME) - ((void) ctx); -#else - if( ctx->ticket_lifetime != 0 ) - { - uint32_t current_time = (uint32_t) mbedtls_time( NULL ); - uint32_t key_time = ctx->keys[ctx->active].generation_time; - - if( current_time > key_time && - current_time - key_time < ctx->ticket_lifetime ) - { - return( 0 ); - } - - ctx->active = 1 - ctx->active; - - return( ssl_ticket_gen_key( ctx, ctx->active ) ); - } - else -#endif /* MBEDTLS_HAVE_TIME */ - return( 0 ); -} - -/* - * Setup context for actual use - */ -int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - mbedtls_cipher_type_t cipher, - uint32_t lifetime ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - - ctx->f_rng = f_rng; - ctx->p_rng = p_rng; - - ctx->ticket_lifetime = lifetime; - - cipher_info = mbedtls_cipher_info_from_type( cipher); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( cipher_info->mode != MBEDTLS_MODE_GCM && - cipher_info->mode != MBEDTLS_MODE_CCM ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 || - ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || - ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} - -/* - * Serialize a session in the following format: - * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) - * n . n+2 peer_cert length = m (0 if no certificate) - * n+3 . n+2+m peer cert ASN.1 - */ -static int ssl_save_session( const mbedtls_ssl_session *session, - unsigned char *buf, size_t buf_len, - size_t *olen ) -{ - unsigned char *p = buf; - size_t left = buf_len; -#if defined(MBEDTLS_X509_CRT_PARSE_C) - size_t cert_len; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( left < sizeof( mbedtls_ssl_session ) ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - memcpy( p, session, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); - left -= sizeof( mbedtls_ssl_session ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( session->peer_cert == NULL ) - cert_len = 0; - else - cert_len = session->peer_cert->raw.len; - - if( left < 3 + cert_len ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - *p++ = (unsigned char)( cert_len >> 16 & 0xFF ); - *p++ = (unsigned char)( cert_len >> 8 & 0xFF ); - *p++ = (unsigned char)( cert_len & 0xFF ); - - if( session->peer_cert != NULL ) - memcpy( p, session->peer_cert->raw.p, cert_len ); - - p += cert_len; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - *olen = p - buf; - - return( 0 ); -} - -/* - * Unserialise session, see ssl_save_session() - */ -static int ssl_load_session( mbedtls_ssl_session *session, - const unsigned char *buf, size_t len ) -{ - const unsigned char *p = buf; - const unsigned char * const end = buf + len; -#if defined(MBEDTLS_X509_CRT_PARSE_C) - size_t cert_len; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( p + sizeof( mbedtls_ssl_session ) > end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - memcpy( session, p, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( p + 3 > end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; - p += 3; - - if( cert_len == 0 ) - { - session->peer_cert = NULL; - } - else - { - int ret; - - if( p + cert_len > end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - - if( session->peer_cert == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - mbedtls_x509_crt_init( session->peer_cert ); - - if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, - p, cert_len ) ) != 0 ) - { - mbedtls_x509_crt_free( session->peer_cert ); - mbedtls_free( session->peer_cert ); - session->peer_cert = NULL; - return( ret ); - } - - p += cert_len; - } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( p != end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - return( 0 ); -} - -/* - * Create session ticket, with the following structure: - * - * struct { - * opaque key_name[4]; - * opaque iv[12]; - * opaque encrypted_state<0..2^16-1>; - * opaque tag[16]; - * } ticket; - * - * The key_name, iv, and length of encrypted_state are the additional - * authenticated data. - */ -int mbedtls_ssl_ticket_write( void *p_ticket, - const mbedtls_ssl_session *session, - unsigned char *start, - const unsigned char *end, - size_t *tlen, - uint32_t *ticket_lifetime ) -{ - int ret; - mbedtls_ssl_ticket_context *ctx = p_ticket; - mbedtls_ssl_ticket_key *key; - unsigned char *key_name = start; - unsigned char *iv = start + 4; - unsigned char *state_len_bytes = iv + 12; - unsigned char *state = state_len_bytes + 2; - unsigned char *tag; - size_t clear_len, ciph_len; - - *tlen = 0; - - if( ctx == NULL || ctx->f_rng == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, - * in addition to session itself, that will be checked when writing it. */ - if( end - start < 4 + 12 + 2 + 16 ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) - goto cleanup; - - key = &ctx->keys[ctx->active]; - - *ticket_lifetime = ctx->ticket_lifetime; - - memcpy( key_name, key->name, 4 ); - - if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 ) - goto cleanup; - - /* Dump session state */ - if( ( ret = ssl_save_session( session, - state, end - state, &clear_len ) ) != 0 || - (unsigned long) clear_len > 65535 ) - { - goto cleanup; - } - state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; - state_len_bytes[1] = ( clear_len ) & 0xff; - - /* Encrypt and authenticate */ - tag = state + clear_len; - if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, - iv, 12, key_name, 4 + 12 + 2, - state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 ) - { - goto cleanup; - } - if( ciph_len != clear_len ) - { - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto cleanup; - } - - *tlen = 4 + 12 + 2 + 16 + ciph_len; - -cleanup: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Select key based on name - */ -static mbedtls_ssl_ticket_key *ssl_ticket_select_key( - mbedtls_ssl_ticket_context *ctx, - const unsigned char name[4] ) -{ - unsigned char i; - - for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) - if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) - return( &ctx->keys[i] ); - - return( NULL ); -} - -/* - * Load session ticket (see mbedtls_ssl_ticket_write for structure) - */ -int mbedtls_ssl_ticket_parse( void *p_ticket, - mbedtls_ssl_session *session, - unsigned char *buf, - size_t len ) -{ - int ret; - mbedtls_ssl_ticket_context *ctx = p_ticket; - mbedtls_ssl_ticket_key *key; - unsigned char *key_name = buf; - unsigned char *iv = buf + 4; - unsigned char *enc_len_p = iv + 12; - unsigned char *ticket = enc_len_p + 2; - unsigned char *tag; - size_t enc_len, clear_len; - - if( ctx == NULL || ctx->f_rng == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* See mbedtls_ssl_ticket_write() */ - if( len < 4 + 12 + 2 + 16 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) - goto cleanup; - - enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; - tag = ticket + enc_len; - - if( len != 4 + 12 + 2 + enc_len + 16 ) - { - ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - goto cleanup; - } - - /* Select key */ - if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) - { - /* We can't know for sure but this is a likely option unless we're - * under attack - this is only informative anyway */ - ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; - goto cleanup; - } - - /* Decrypt and authenticate */ - if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12, - key_name, 4 + 12 + 2, ticket, enc_len, - ticket, &clear_len, tag, 16 ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) - ret = MBEDTLS_ERR_SSL_INVALID_MAC; - - goto cleanup; - } - if( clear_len != enc_len ) - { - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto cleanup; - } - - /* Actually load session */ - if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 ) - goto cleanup; - -#if defined(MBEDTLS_HAVE_TIME) - { - /* Check for expiration */ - mbedtls_time_t current_time = mbedtls_time( NULL ); - - if( current_time < session->start || - (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) - { - ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; - goto cleanup; - } - } -#endif - -cleanup: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Free context - */ -void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) -{ - mbedtls_cipher_free( &ctx->keys[0].ctx ); - mbedtls_cipher_free( &ctx->keys[1].ctx ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - - mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); -} - -#endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/components/security/mbedtls/src/ssl_tls.c b/components/security/mbedtls/src/ssl_tls.c deleted file mode 100644 index a16b6211..00000000 --- a/components/security/mbedtls/src/ssl_tls.c +++ /dev/null @@ -1,7807 +0,0 @@ -/* - * SSLv3/TLSv1 shared 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) - */ -/* - * The SSL 3.0 specification was drafted by Netscape in 1996, - * and became an IETF standard in 1999. - * - * http://wp.netscape.com/eng/ssl3/ - * http://www.ietf.org/rfc/rfc2246.txt - * http://www.ietf.org/rfc/rfc4346.txt - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_TLS_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" - -#include - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#include "mbedtls/oid.h" -#endif - -/* 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; -} - -/* Length of the "epoch" field in the record header */ -static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 2 ); -#else - ((void) ssl); -#endif - return( 0 ); -} - -/* - * Start a timer. - * Passing millisecs = 0 cancels a running timer. - */ -static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) -{ - if( ssl->f_set_timer == NULL ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); - ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); -} - -/* - * Return -1 is timer is expired, 0 if it isn't. - */ -static int ssl_check_timer( mbedtls_ssl_context *ssl ) -{ - if( ssl->f_get_timer == NULL ) - return( 0 ); - - if( ssl->f_get_timer( ssl->p_timer ) == 2 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); - return( -1 ); - } - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * Double the retransmit timeout value, within the allowed range, - * returning -1 if the maximum value has already been reached. - */ -static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) -{ - uint32_t new_timeout; - - if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) - return( -1 ); - - new_timeout = 2 * ssl->handshake->retransmit_timeout; - - /* Avoid arithmetic overflow and range overflow */ - if( new_timeout < ssl->handshake->retransmit_timeout || - new_timeout > ssl->conf->hs_timeout_max ) - { - new_timeout = ssl->conf->hs_timeout_max; - } - - ssl->handshake->retransmit_timeout = new_timeout; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", - ssl->handshake->retransmit_timeout ) ); - - return( 0 ); -} - -static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) -{ - ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", - ssl->handshake->retransmit_timeout ) ); -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -/* - * Convert max_fragment_length codes to length. - * RFC 6066 says: - * enum{ - * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) - * } MaxFragmentLength; - * and we add 0 -> extension unused - */ -static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = -{ - MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ - 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ - 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ - 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ - 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ -}; -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_CLI_C) -static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src ) -{ - mbedtls_ssl_session_free( dst ); - memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( src->peer_cert != NULL ) - { - int ret; - - dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); - if( dst->peer_cert == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - mbedtls_x509_crt_init( dst->peer_cert ); - - if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, - src->peer_cert->raw.len ) ) != 0 ) - { - mbedtls_free( dst->peer_cert ); - dst->peer_cert = NULL; - return( ret ); - } - } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - if( src->ticket != NULL ) - { - dst->ticket = mbedtls_calloc( 1, src->ticket_len ); - if( dst->ticket == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( dst->ticket, src->ticket, src->ticket_len ); - } -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - - return( 0 ); -} -#endif /* MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) -int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen ) = NULL; -int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; -int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - -/* - * Key material generation - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) -static int ssl3_prf( const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t i; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char padding[16]; - unsigned char sha1sum[20]; - ((void)label); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - /* - * SSLv3: - * block = - * MD5( secret + SHA1( 'A' + secret + random ) ) + - * MD5( secret + SHA1( 'BB' + secret + random ) ) + - * MD5( secret + SHA1( 'CCC' + secret + random ) ) + - * ... - */ - for( i = 0; i < dlen / 16; i++ ) - { - memset( padding, (unsigned char) ('A' + i), 1 + i ); - - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, padding, 1 + i ); - mbedtls_sha1_update( &sha1, secret, slen ); - mbedtls_sha1_update( &sha1, random, rlen ); - mbedtls_sha1_finish( &sha1, sha1sum ); - - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, secret, slen ); - mbedtls_md5_update( &md5, sha1sum, 20 ); - mbedtls_md5_finish( &md5, dstbuf + i * 16 ); - } - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - mbedtls_zeroize( padding, sizeof( padding ) ); - mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static int tls1_prf( const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t nb, hs; - size_t i, j, k; - const unsigned char *S1, *S2; - unsigned char tmp[128]; - unsigned char h_i[20]; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - int ret; - - mbedtls_md_init( &md_ctx ); - - if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - hs = ( slen + 1 ) / 2; - S1 = secret; - S2 = secret + slen - hs; - - nb = strlen( label ); - memcpy( tmp + 20, label, nb ); - memcpy( tmp + 20 + nb, random, rlen ); - nb += rlen; - - /* - * First compute P_md5(secret,label+random)[0..dlen] - */ - if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - mbedtls_md_hmac_starts( &md_ctx, S1, hs ); - mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); - mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); - - for( i = 0; i < dlen; i += 16 ) - { - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); - mbedtls_md_hmac_finish( &md_ctx, h_i ); - - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); - mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); - - k = ( i + 16 > dlen ) ? dlen % 16 : 16; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = h_i[j]; - } - - mbedtls_md_free( &md_ctx ); - - /* - * XOR out with P_sha1(secret,label+random)[0..dlen] - */ - if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - mbedtls_md_hmac_starts( &md_ctx, S2, hs ); - mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); - mbedtls_md_hmac_finish( &md_ctx, tmp ); - - for( i = 0; i < dlen; i += 20 ) - { - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); - mbedtls_md_hmac_finish( &md_ctx, h_i ); - - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); - mbedtls_md_hmac_finish( &md_ctx, tmp ); - - k = ( i + 20 > dlen ) ? dlen % 20 : 20; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); - } - - mbedtls_md_free( &md_ctx ); - - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( h_i, sizeof( h_i ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -static int tls_prf_generic( mbedtls_md_type_t md_type, - const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t nb; - size_t i, j, k, md_len; - unsigned char tmp[128]; - unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - int ret; - - mbedtls_md_init( &md_ctx ); - - if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - - md_len = mbedtls_md_get_size( md_info ); - - if( sizeof( tmp ) < md_len + strlen( label ) + rlen ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - nb = strlen( label ); - memcpy( tmp + md_len, label, nb ); - memcpy( tmp + md_len + nb, random, rlen ); - nb += rlen; - - /* - * Compute P_(secret, label + random)[0..dlen] - */ - if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - mbedtls_md_hmac_starts( &md_ctx, secret, slen ); - mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); - mbedtls_md_hmac_finish( &md_ctx, tmp ); - - for( i = 0; i < dlen; i += md_len ) - { - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); - mbedtls_md_hmac_finish( &md_ctx, h_i ); - - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); - mbedtls_md_hmac_finish( &md_ctx, tmp ); - - k = ( i + md_len > dlen ) ? dlen % md_len : md_len; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = h_i[j]; - } - - mbedtls_md_free( &md_ctx ); - - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( h_i, sizeof( h_i ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SHA256_C) -static int tls_prf_sha256( const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, - label, random, rlen, dstbuf, dlen ) ); -} -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) -static int tls_prf_sha384( const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, - label, random, rlen, dstbuf, dlen ) ); -} -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * ); -static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * ); -static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); -static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * ); -static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); -#endif - -#if defined(MBEDTLS_SHA512_C) -static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); -static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * ); -static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - unsigned char tmp[64]; - unsigned char keyblk[256]; - unsigned char *key1; - unsigned char *key2; - unsigned char *mac_enc; - unsigned char *mac_dec; - size_t iv_copy_len; - const mbedtls_cipher_info_t *cipher_info; - const mbedtls_md_info_t *md_info; - - mbedtls_ssl_session *session = ssl->session_negotiate; - mbedtls_ssl_transform *transform = ssl->transform_negotiate; - mbedtls_ssl_handshake_params *handshake = ssl->handshake; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); - - cipher_info = mbedtls_cipher_info_from_type( transform->ciphersuite_info->cipher ); - if( cipher_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", - transform->ciphersuite_info->cipher ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - md_info = mbedtls_md_info_from_type( transform->ciphersuite_info->mac ); - if( md_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found", - transform->ciphersuite_info->mac ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - handshake->tls_prf = ssl3_prf; - handshake->calc_verify = ssl_calc_verify_ssl; - handshake->calc_finished = ssl_calc_finished_ssl; - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) - { - handshake->tls_prf = tls1_prf; - handshake->calc_verify = ssl_calc_verify_tls; - handshake->calc_finished = ssl_calc_finished_tls; - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - { - handshake->tls_prf = tls_prf_sha384; - handshake->calc_verify = ssl_calc_verify_tls_sha384; - handshake->calc_finished = ssl_calc_finished_tls_sha384; - } - else -#endif -#if defined(MBEDTLS_SHA256_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - handshake->tls_prf = tls_prf_sha256; - handshake->calc_verify = ssl_calc_verify_tls_sha256; - handshake->calc_finished = ssl_calc_finished_tls_sha256; - } - else -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * SSLv3: - * master = - * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) - * - * TLSv1+: - * master = PRF( premaster, "master secret", randbytes )[0..47] - */ - if( handshake->resume == 0 ) - { - MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, - handshake->pmslen ); - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) - { - unsigned char session_hash[48]; - size_t hash_len; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); - - ssl->handshake->calc_verify( ssl, session_hash ); - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { -#if defined(MBEDTLS_SHA512_C) - if( ssl->transform_negotiate->ciphersuite_info->mac == - MBEDTLS_MD_SHA384 ) - { - hash_len = 48; - } - else -#endif - hash_len = 32; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - hash_len = 36; - - MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); - - ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - "extended master secret", - session_hash, hash_len, - session->master, 48 ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } - - } - else -#endif - ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - "master secret", - handshake->randbytes, 64, - session->master, 48 ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } - - mbedtls_zeroize( handshake->premaster, sizeof(handshake->premaster) ); - } - else - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); - - /* - * Swap the client and server random values. - */ - memcpy( tmp, handshake->randbytes, 64 ); - memcpy( handshake->randbytes, tmp + 32, 32 ); - memcpy( handshake->randbytes + 32, tmp, 32 ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); - - /* - * SSLv3: - * key block = - * MD5( master + SHA1( 'A' + master + randbytes ) ) + - * MD5( master + SHA1( 'BB' + master + randbytes ) ) + - * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + - * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + - * ... - * - * TLSv1: - * key block = PRF( master, "key expansion", randbytes ) - */ - ret = handshake->tls_prf( session->master, 48, "key expansion", - handshake->randbytes, 64, keyblk, 256 ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", - mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); - MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); - MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); - - mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); - - /* - * Determine the appropriate key, IV and MAC length. - */ - - transform->keylen = cipher_info->key_bitlen / 8; - - if( cipher_info->mode == MBEDTLS_MODE_GCM || - cipher_info->mode == MBEDTLS_MODE_CCM ) - { - transform->maclen = 0; - - transform->ivlen = 12; - transform->fixed_ivlen = 4; - - /* Minimum length is expicit IV + tag */ - transform->minlen = transform->ivlen - transform->fixed_ivlen - + ( transform->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); - } - else - { - /* Initialize HMAC contexts */ - if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || - ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); - return( ret ); - } - - /* Get MAC length */ - transform->maclen = mbedtls_md_get_size( md_info ); - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - /* - * If HMAC is to be truncated, we shall keep the leftmost bytes, - * (rfc 6066 page 13 or rfc 2104 section 4), - * so we only need to adjust the length here. - */ - if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) - transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - - /* IV length */ - transform->ivlen = cipher_info->iv_size; - - /* Minimum length */ - if( cipher_info->mode == MBEDTLS_MODE_STREAM ) - transform->minlen = transform->maclen; - else - { - /* - * GenericBlockCipher: - * 1. if EtM is in use: one block plus MAC - * otherwise: * first multiple of blocklen greater than maclen - * 2. IV except for SSL3 and TLS 1.0 - */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) - { - transform->minlen = transform->maclen - + cipher_info->block_size; - } - else -#endif - { - transform->minlen = transform->maclen - + cipher_info->block_size - - transform->maclen % cipher_info->block_size; - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) - ; /* No need to adjust minlen */ - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - transform->minlen += transform->ivlen; - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", - transform->keylen, transform->minlen, transform->ivlen, - transform->maclen ) ); - - /* - * Finally setup the cipher contexts, IVs and MAC secrets. - */ -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - key1 = keyblk + transform->maclen * 2; - key2 = keyblk + transform->maclen * 2 + transform->keylen; - - mac_enc = keyblk; - mac_dec = keyblk + transform->maclen; - - /* - * This is not used in TLS v1.1. - */ - iv_copy_len = ( transform->fixed_ivlen ) ? - transform->fixed_ivlen : transform->ivlen; - memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); - memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, - iv_copy_len ); - } - else -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - { - key1 = keyblk + transform->maclen * 2 + transform->keylen; - key2 = keyblk + transform->maclen * 2; - - mac_enc = keyblk + transform->maclen; - mac_dec = keyblk; - - /* - * This is not used in TLS v1.1. - */ - iv_copy_len = ( transform->fixed_ivlen ) ? - transform->fixed_ivlen : transform->ivlen; - memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); - memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, - iv_copy_len ); - } - else -#endif /* MBEDTLS_SSL_SRV_C */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( transform->maclen > sizeof transform->mac_enc ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - memcpy( transform->mac_enc, mac_enc, transform->maclen ); - memcpy( transform->mac_dec, mac_dec, transform->maclen ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) - { - mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen ); - mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen ); - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_init != NULL ) - { - int ret = 0; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); - - if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen, - transform->iv_enc, transform->iv_dec, - iv_copy_len, - mac_enc, mac_dec, - transform->maclen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - if( ssl->conf->f_export_keys != NULL ) - { - ssl->conf->f_export_keys( ssl->conf->p_export_keys, - session->master, keyblk, - transform->maclen, transform->keylen, - iv_copy_len ); - } -#endif - - if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, - cipher_info ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); - return( ret ); - } - - if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, - cipher_info ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); - return( ret ); - } - - if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, - cipher_info->key_bitlen, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); - return( ret ); - } - - if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, - cipher_info->key_bitlen, - MBEDTLS_DECRYPT ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); - return( ret ); - } - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - if( cipher_info->mode == MBEDTLS_MODE_CBC ) - { - if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, - MBEDTLS_PADDING_NONE ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); - return( ret ); - } - - if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, - MBEDTLS_PADDING_NONE ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - - mbedtls_zeroize( keyblk, sizeof( keyblk ) ); - -#if defined(MBEDTLS_ZLIB_SUPPORT) - // Initialize compression - // - if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - if( ssl->compress_buf == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); - ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN ); - if( ssl->compress_buf == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - MBEDTLS_SSL_BUFFER_LEN ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); - - memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); - memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); - - if( deflateInit( &transform->ctx_deflate, - Z_DEFAULT_COMPRESSION ) != Z_OK || - inflateInit( &transform->ctx_inflate ) != Z_OK ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); - return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); - } - } -#endif /* MBEDTLS_ZLIB_SUPPORT */ - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) -{ - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char pad_1[48]; - unsigned char pad_2[48]; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); - mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - - memset( pad_1, 0x36, 48 ); - memset( pad_2, 0x5C, 48 ); - - mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); - mbedtls_md5_update( &md5, pad_1, 48 ); - mbedtls_md5_finish( &md5, hash ); - - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); - mbedtls_md5_update( &md5, pad_2, 48 ); - mbedtls_md5_update( &md5, hash, 16 ); - mbedtls_md5_finish( &md5, hash ); - - mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); - mbedtls_sha1_update( &sha1, pad_1, 40 ); - mbedtls_sha1_finish( &sha1, hash + 16 ); - - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); - mbedtls_sha1_update( &sha1, pad_2, 40 ); - mbedtls_sha1_update( &sha1, hash + 16, 20 ); - mbedtls_sha1_finish( &sha1, hash + 16 ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - return; -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) -{ - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); - mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - - mbedtls_md5_finish( &md5, hash ); - mbedtls_sha1_finish( &sha1, hash + 16 ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - return; -} -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) - -#if defined(MBEDTLS_SHA256_ALT) -void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] ) -{ - mbedtls_sha256_context sha256; - - mbedtls_sha256_init_alt( &sha256 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); - - mbedtls_sha256_clone_alt( &sha256, &ssl->handshake->fin_sha256 ); - mbedtls_sha256_finish_alt( &sha256, hash ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_sha256_free_alt( &sha256 ); - - return; -} - -#else /* MBEDTLS_SHA256_ALT */ - -void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] ) -{ - mbedtls_sha256_context sha256; - - mbedtls_sha256_init( &sha256 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); - - mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); - mbedtls_sha256_finish( &sha256, hash ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_sha256_free( &sha256 ); - - return; -} - -#endif /* MBEDTLS_SHA256_ALT */ - -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) -void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] ) -{ - mbedtls_sha512_context sha512; - - mbedtls_sha512_init( &sha512 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); - - mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); - mbedtls_sha512_finish( &sha512, hash ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_sha512_free( &sha512 ); - - return; -} -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) -{ - unsigned char *p = ssl->handshake->premaster; - unsigned char *end = p + sizeof( ssl->handshake->premaster ); - const unsigned char *psk = ssl->conf->psk; - size_t psk_len = ssl->conf->psk_len; - - /* If the psk callback was called, use its result */ - if( ssl->handshake->psk != NULL ) - { - psk = ssl->handshake->psk; - psk_len = ssl->handshake->psk_len; - } - - /* - * PMS = struct { - * opaque other_secret<0..2^16-1>; - * opaque psk<0..2^16-1>; - * }; - * with "other_secret" depending on the particular key exchange - */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) - { - if( end - p < 2 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - *(p++) = (unsigned char)( psk_len >> 8 ); - *(p++) = (unsigned char)( psk_len ); - - if( end < p || (size_t)( end - p ) < psk_len ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - memset( p, 0, psk_len ); - p += psk_len; - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - /* - * other_secret already set by the ClientKeyExchange message, - * and is 48 bytes long - */ - *p++ = 0; - *p++ = 48; - p += 48; - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - int ret; - size_t len; - - /* Write length only when we know the actual value */ - if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, - p + 2, end - ( p + 2 ), &len, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); - return( ret ); - } - *(p++) = (unsigned char)( len >> 8 ); - *(p++) = (unsigned char)( len ); - p += len; - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - int ret; - size_t zlen; - - if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, - p + 2, end - ( p + 2 ), - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); - return( ret ); - } - - *(p++) = (unsigned char)( zlen >> 8 ); - *(p++) = (unsigned char)( zlen ); - p += zlen; - - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* opaque psk<0..2^16-1>; */ - if( end - p < 2 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - *(p++) = (unsigned char)( psk_len >> 8 ); - *(p++) = (unsigned char)( psk_len ); - - if( end < p || (size_t)( end - p ) < psk_len ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - memcpy( p, psk, psk_len ); - p += psk_len; - - ssl->handshake->pmslen = p - ssl->handshake->premaster; - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -/* - * SSLv3.0 MAC functions - */ -static void ssl_mac( mbedtls_md_context_t *md_ctx, unsigned char *secret, - unsigned char *buf, size_t len, - unsigned char *ctr, int type ) -{ - unsigned char header[11]; - unsigned char padding[48]; - int padlen; - int md_size = mbedtls_md_get_size( md_ctx->md_info ); - int md_type = mbedtls_md_get_type( md_ctx->md_info ); - - /* Only MD5 and SHA-1 supported */ - if( md_type == MBEDTLS_MD_MD5 ) - padlen = 48; - else - padlen = 40; - - memcpy( header, ctr, 8 ); - header[ 8] = (unsigned char) type; - header[ 9] = (unsigned char)( len >> 8 ); - header[10] = (unsigned char)( len ); - - memset( padding, 0x36, padlen ); - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, secret, md_size ); - mbedtls_md_update( md_ctx, padding, padlen ); - mbedtls_md_update( md_ctx, header, 11 ); - mbedtls_md_update( md_ctx, buf, len ); - mbedtls_md_finish( md_ctx, buf + len ); - - memset( padding, 0x5C, padlen ); - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, secret, md_size ); - mbedtls_md_update( md_ctx, padding, padlen ); - mbedtls_md_update( md_ctx, buf + len, md_size ); - mbedtls_md_finish( md_ctx, buf + len ); -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ - ( defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) ) -#define SSL_SOME_MODES_USE_MAC -#endif - -/* - * Encryption/decryption functions - */ -static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) -{ - mbedtls_cipher_mode_t mode; - int auth_done = 0; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); - - if( ssl->session_out == NULL || ssl->transform_out == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", - ssl->out_msg, ssl->out_msglen ); - - /* - * Add MAC before if needed - */ -#if defined(SSL_SOME_MODES_USE_MAC) - if( mode == MBEDTLS_MODE_STREAM || - ( mode == MBEDTLS_MODE_CBC -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - && ssl->session_out->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED -#endif - ) ) - { -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl_mac( &ssl->transform_out->md_ctx_enc, - ssl->transform_out->mac_enc, - ssl->out_msg, ssl->out_msglen, - ssl->out_ctr, ssl->out_msgtype ); - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) - { - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 ); - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 ); - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 ); - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, - ssl->out_msg, ssl->out_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, - ssl->out_msg + ssl->out_msglen ); - mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", - ssl->out_msg + ssl->out_msglen, - ssl->transform_out->maclen ); - - ssl->out_msglen += ssl->transform_out->maclen; - auth_done++; - } -#endif /* AEAD not the only option */ - - /* - * Encrypt - */ -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if( mode == MBEDTLS_MODE_STREAM ) - { - int ret; - size_t olen = 0; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); - - if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, - ssl->out_msg, ssl->out_msglen, - ssl->out_msg, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( ssl->out_msglen != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) - if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) - { - int ret; - size_t enc_msglen, olen; - unsigned char *enc_msg; - unsigned char add_data[13]; - unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; - - memcpy( add_data, ssl->out_ctr, 8 ); - add_data[8] = ssl->out_msgtype; - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, add_data + 9 ); - add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; - add_data[12] = ssl->out_msglen & 0xFF; - - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); - - /* - * Generate IV - */ - if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) - { - /* Reminder if we ever add an AEAD mode with a different size */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, - ssl->out_ctr, 8 ); - memcpy( ssl->out_iv, ssl->out_ctr, 8 ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, - ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); - - /* - * Fix pointer positions and message length with added IV - */ - enc_msg = ssl->out_msg; - enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); - - /* - * Encrypt and authenticate - */ - if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, - add_data, 13, - enc_msg, enc_msglen, - enc_msg, &olen, - enc_msg + enc_msglen, taglen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); - return( ret ); - } - - if( olen != enc_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->out_msglen += taglen; - auth_done++; - - MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); - } - else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) - if( mode == MBEDTLS_MODE_CBC ) - { - int ret; - unsigned char *enc_msg; - size_t enc_msglen, padlen, olen = 0, i; - - padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % - ssl->transform_out->ivlen; - if( padlen == ssl->transform_out->ivlen ) - padlen = 0; - - for( i = 0; i <= padlen; i++ ) - ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; - - ssl->out_msglen += padlen + 1; - - enc_msglen = ssl->out_msglen; - enc_msg = ssl->out_msg; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * Prepend per-record IV for block cipher in TLS v1.1 and up as per - * Method 1 (6.2.3.2. in RFC4346 and RFC5246) - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* - * Generate IV - */ - ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc, - ssl->transform_out->ivlen ); - if( ret != 0 ) - return( ret ); - - memcpy( ssl->out_iv, ssl->transform_out->iv_enc, - ssl->transform_out->ivlen ); - - /* - * Fix pointer positions and message length with added IV - */ - enc_msg = ssl->out_msg; - enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->transform_out->ivlen; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of IV and %d bytes of padding", - ssl->out_msglen, ssl->transform_out->ivlen, - padlen + 1 ) ); - - if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, - enc_msg, enc_msglen, - enc_msg, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( enc_msglen != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* - * Save IV in SSL3 and TLS1 - */ - memcpy( ssl->transform_out->iv_enc, - ssl->transform_out->cipher_ctx_enc.iv, - ssl->transform_out->ivlen ); - } -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( auth_done == 0 ) - { - /* - * MAC(MAC_write_key, seq_num + - * TLSCipherText.type + - * TLSCipherText.version + - * length_of( (IV +) ENC(...) ) + - * IV + // except for TLS 1.0 - * ENC(content + padding + padding_length)); - */ - unsigned char pseudo_hdr[13]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); - - memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 ); - memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 ); - pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF ); - pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); - - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, - ssl->out_iv, ssl->out_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, - ssl->out_iv + ssl->out_msglen ); - mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); - - ssl->out_msglen += ssl->transform_out->maclen; - auth_done++; - } -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - } - else -#endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* Make extra sure authentication was performed, exactly once */ - if( auth_done != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); - - return( 0 ); -} - -#define SSL_MAX_MAC_SIZE 48 - -static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) -{ - size_t i; - mbedtls_cipher_mode_t mode; - int auth_done = 0; -#if defined(SSL_SOME_MODES_USE_MAC) - size_t padlen = 0, correct = 1; -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); - - if( ssl->session_in == NULL || ssl->transform_in == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec ); - - if( ssl->in_msglen < ssl->transform_in->minlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", - ssl->in_msglen, ssl->transform_in->minlen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if( mode == MBEDTLS_MODE_STREAM ) - { - int ret; - size_t olen = 0; - - padlen = 0; - - if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, - ssl->in_msg, ssl->in_msglen, - ssl->in_msg, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( ssl->in_msglen != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) - if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) - { - int ret; - size_t dec_msglen, olen; - unsigned char *dec_msg; - unsigned char *dec_msg_result; - unsigned char add_data[13]; - unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; - size_t explicit_iv_len = ssl->transform_in->ivlen - - ssl->transform_in->fixed_ivlen; - - if( ssl->in_msglen < explicit_iv_len + taglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " - "+ taglen (%d)", ssl->in_msglen, - explicit_iv_len, taglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - dec_msglen = ssl->in_msglen - explicit_iv_len - taglen; - - dec_msg = ssl->in_msg; - dec_msg_result = ssl->in_msg; - ssl->in_msglen = dec_msglen; - - memcpy( add_data, ssl->in_ctr, 8 ); - add_data[8] = ssl->in_msgtype; - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, add_data + 9 ); - add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; - add_data[12] = ssl->in_msglen & 0xFF; - - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); - - memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, - ssl->in_iv, - ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, - ssl->transform_in->ivlen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); - - /* - * Decrypt and authenticate - */ - if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, - add_data, 13, - dec_msg, dec_msglen, - dec_msg_result, &olen, - dec_msg + dec_msglen, taglen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); - - if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - - return( ret ); - } - auth_done++; - - if( olen != dec_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) - if( mode == MBEDTLS_MODE_CBC ) - { - /* - * Decrypt and check the padding - */ - int ret; - unsigned char *dec_msg; - unsigned char *dec_msg_result; - size_t dec_msglen; - size_t minlen = 0; - size_t olen = 0; - - /* - * Check immediate ciphertext sanity - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - minlen += ssl->transform_in->ivlen; -#endif - - if( ssl->in_msglen < minlen + ssl->transform_in->ivlen || - ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " - "+ 1 ) ( + expl IV )", ssl->in_msglen, - ssl->transform_in->ivlen, - ssl->transform_in->maclen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - - dec_msglen = ssl->in_msglen; - dec_msg = ssl->in_msg; - dec_msg_result = ssl->in_msg; - - /* - * Authenticate before decrypt if enabled - */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) - { - unsigned char computed_mac[SSL_MAX_MAC_SIZE]; - unsigned char pseudo_hdr[13]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); - - dec_msglen -= ssl->transform_in->maclen; - ssl->in_msglen -= ssl->transform_in->maclen; - - memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 ); - memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 ); - pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF ); - pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); - - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, - ssl->in_iv, ssl->in_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac ); - mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, - ssl->transform_in->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", computed_mac, - ssl->transform_in->maclen ); - - if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac, - ssl->transform_in->maclen ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); - - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - auth_done++; - } -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - - /* - * Check length sanity - */ - if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", - ssl->in_msglen, ssl->transform_in->ivlen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * Initialize for prepended IV for block cipher in TLS v1.1 and up - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - dec_msglen -= ssl->transform_in->ivlen; - ssl->in_msglen -= ssl->transform_in->ivlen; - - for( i = 0; i < ssl->transform_in->ivlen; i++ ) - ssl->transform_in->iv_dec[i] = ssl->in_iv[i]; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ - - if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, - dec_msg, dec_msglen, - dec_msg_result, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( dec_msglen != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* - * Save IV in SSL3 and TLS1 - */ - memcpy( ssl->transform_in->iv_dec, - ssl->transform_in->cipher_ctx_dec.iv, - ssl->transform_in->ivlen ); - } -#endif - - padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; - - if( ssl->in_msglen < ssl->transform_in->maclen + padlen && - auth_done == 0 ) - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", - ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); -#endif - padlen = 0; - correct = 0; - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( padlen > ssl->transform_in->ivlen ) - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " - "should be no more than %d", - padlen, ssl->transform_in->ivlen ) ); -#endif - correct = 0; - } - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* - * TLSv1+: always check the padding up to the first failure - * and fake check up to 256 bytes of padding - */ - size_t pad_count = 0, real_count = 1; - size_t padding_idx = ssl->in_msglen - padlen - 1; - - /* - * Padding is guaranteed to be incorrect if: - * 1. padlen >= ssl->in_msglen - * - * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN + - * ssl->transform_in->maclen - * - * In both cases we reset padding_idx to a safe value (0) to - * prevent out-of-buffer reads. - */ - correct &= ( ssl->in_msglen >= padlen + 1 ); - correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + - ssl->transform_in->maclen ); - - padding_idx *= correct; - - for( i = 1; i <= 256; i++ ) - { - real_count &= ( i <= padlen ); - pad_count += real_count * - ( ssl->in_msg[padding_idx + i] == padlen - 1 ); - } - - correct &= ( pad_count == padlen ); /* Only 1 on correct padding */ - -#if defined(MBEDTLS_SSL_DEBUG_ALL) - if( padlen > 0 && correct == 0 ) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); -#endif - padlen &= correct * 0x1FF; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->in_msglen -= padlen; - } - else -#endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", - ssl->in_msg, ssl->in_msglen ); - - /* - * Authenticate if not done yet. - * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). - */ -#if defined(SSL_SOME_MODES_USE_MAC) - if( auth_done == 0 ) - { - unsigned char tmp[SSL_MAX_MAC_SIZE]; - - ssl->in_msglen -= ssl->transform_in->maclen; - - ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); - ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); - - memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl_mac( &ssl->transform_in->md_ctx_dec, - ssl->transform_in->mac_dec, - ssl->in_msg, ssl->in_msglen, - ssl->in_ctr, ssl->in_msgtype ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* - * Process MAC and always update for padlen afterwards to make - * total time independent of padlen - * - * extra_run compensates MAC check for padlen - * - * Known timing attacks: - * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) - * - * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values - * correctly. (We round down instead of up, so -56 is the correct - * value for our calculations instead of -55) - */ - size_t j, extra_run = 0; - extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - - ( 13 + ssl->in_msglen + 8 ) / 64; - - extra_run &= correct * 0xFF; - - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 8 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_hdr, 3 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, - ssl->in_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, - ssl->in_msg + ssl->in_msglen ); - /* Call mbedtls_md_process at least once due to cache attacks */ - for( j = 0; j < extra_run + 1; j++ ) - mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); - - mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, - ssl->transform_in->maclen ); - - if( mbedtls_ssl_safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen, - ssl->transform_in->maclen ) != 0 ) - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); -#endif - correct = 0; - } - auth_done++; - - /* - * Finally check the correct flag - */ - if( correct == 0 ) - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } -#endif /* SSL_SOME_MODES_USE_MAC */ - - /* Make extra sure authentication was performed, exactly once */ - if( auth_done != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( ssl->in_msglen == 0 ) - { - ssl->nb_zero++; - - /* - * Three or more empty messages may be a DoS attack - * (excessive CPU consumption). - */ - if( ssl->nb_zero > 3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " - "messages, possible DoS attack" ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - } - else - ssl->nb_zero = 0; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ; /* in_ctr read from peer, not maintained internally */ - } - else -#endif - { - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->in_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); - - return( 0 ); -} - -#undef MAC_NONE -#undef MAC_PLAINTEXT -#undef MAC_CIPHERTEXT - -#if defined(MBEDTLS_ZLIB_SUPPORT) -/* - * Compression/decompression functions - */ -static int ssl_compress_buf( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *msg_post = ssl->out_msg; - size_t len_pre = ssl->out_msglen; - unsigned char *msg_pre = ssl->compress_buf; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); - - if( len_pre == 0 ) - return( 0 ); - - memcpy( msg_pre, ssl->out_msg, len_pre ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", - ssl->out_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", - ssl->out_msg, ssl->out_msglen ); - - ssl->transform_out->ctx_deflate.next_in = msg_pre; - ssl->transform_out->ctx_deflate.avail_in = len_pre; - ssl->transform_out->ctx_deflate.next_out = msg_post; - ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN; - - ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); - if( ret != Z_OK ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); - return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); - } - - ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN - - ssl->transform_out->ctx_deflate.avail_out; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", - ssl->out_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", - ssl->out_msg, ssl->out_msglen ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); - - return( 0 ); -} - -static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *msg_post = ssl->in_msg; - size_t len_pre = ssl->in_msglen; - unsigned char *msg_pre = ssl->compress_buf; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); - - if( len_pre == 0 ) - return( 0 ); - - memcpy( msg_pre, ssl->in_msg, len_pre ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", - ssl->in_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", - ssl->in_msg, ssl->in_msglen ); - - ssl->transform_in->ctx_inflate.next_in = msg_pre; - ssl->transform_in->ctx_inflate.avail_in = len_pre; - ssl->transform_in->ctx_inflate.next_out = msg_post; - ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_MAX_CONTENT_LEN; - - ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); - if( ret != Z_OK ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); - return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); - } - - ssl->in_msglen = MBEDTLS_SSL_MAX_CONTENT_LEN - - ssl->transform_in->ctx_inflate.avail_out; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", - ssl->in_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", - ssl->in_msg, ssl->in_msglen ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) -static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) -{ - /* If renegotiation is not enforced, retransmit until we would reach max - * timeout if we were using the usual handshake doubling scheme */ - if( ssl->conf->renego_max_records < 0 ) - { - uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; - unsigned char doublings = 1; - - while( ratio != 0 ) - { - ++doublings; - ratio >>= 1; - } - - if( ++ssl->renego_records_seen > doublings ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); - return( 0 ); - } - } - - return( ssl_write_hello_request( ssl ) ); -} -#endif -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ - -/* - * Fill the input message buffer by appending data to it. - * The amount of data already fetched is in ssl->in_left. - * - * If we return 0, is it guaranteed that (at least) nb_want bytes are - * available (from this read and/or a previous one). Otherwise, an error code - * is returned (possibly EOF or WANT_READ). - * - * With stream transport (TLS) on success ssl->in_left == nb_want, but - * with datagram transport (DTLS) on success ssl->in_left >= nb_want, - * since we always read a whole datagram at once. - * - * For DTLS, it is up to the caller to set ssl->next_record_offset when - * they're done reading a record. - */ -int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) -{ - int ret; - size_t len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); - - if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " - "or mbedtls_ssl_set_bio()" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - uint32_t timeout; - - /* Just to be sure */ - if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " - "mbedtls_ssl_set_timer_cb() for DTLS" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * The point is, we need to always read a full datagram at once, so we - * sometimes read more then requested, and handle the additional data. - * It could be the rest of the current record (while fetching the - * header) and/or some other records in the same datagram. - */ - - /* - * Move to the next record in the already read datagram if applicable - */ - if( ssl->next_record_offset != 0 ) - { - if( ssl->in_left < ssl->next_record_offset ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->in_left -= ssl->next_record_offset; - - if( ssl->in_left != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", - ssl->next_record_offset ) ); - memmove( ssl->in_hdr, - ssl->in_hdr + ssl->next_record_offset, - ssl->in_left ); - } - - ssl->next_record_offset = 0; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - - /* - * Done if we already have enough data. - */ - if( nb_want <= ssl->in_left) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); - return( 0 ); - } - - /* - * A record can't be split accross datagrams. If we need to read but - * are not at the beginning of a new record, the caller did something - * wrong. - */ - if( ssl->in_left != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * Don't even try to read if time's out already. - * This avoids by-passing the timer when repeatedly receiving messages - * that will end up being dropped. - */ - if( ssl_check_timer( ssl ) != 0 ) - ret = MBEDTLS_ERR_SSL_TIMEOUT; - else - { - len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - timeout = ssl->handshake->retransmit_timeout; - else - timeout = ssl->conf->read_timeout; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); - - if( ssl->f_recv_timeout != NULL ) - ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, - timeout ); - else - ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); - - if( ret == 0 ) - return( MBEDTLS_ERR_SSL_CONN_EOF ); - } - - if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); - ssl_set_timer( ssl, 0 ); - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ssl_double_retransmit_timeout( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); - return( MBEDTLS_ERR_SSL_TIMEOUT ); - } - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) - else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ - } - - if( ret < 0 ) - return( ret ); - - ssl->in_left = ret; - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - - while( ssl->in_left < nb_want ) - { - len = nb_want - ssl->in_left; - - if( ssl_check_timer( ssl ) != 0 ) - ret = MBEDTLS_ERR_SSL_TIMEOUT; - else - { - if( ssl->f_recv_timeout != NULL ) - { - ret = ssl->f_recv_timeout( ssl->p_bio, - ssl->in_hdr + ssl->in_left, len, - ssl->conf->read_timeout ); - } - else - { - ret = ssl->f_recv( ssl->p_bio, - ssl->in_hdr + ssl->in_left, len ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); - - if( ret == 0 ) - return( MBEDTLS_ERR_SSL_CONN_EOF ); - - if( ret < 0 ) - return( ret ); - - ssl->in_left += ret; - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); - - return( 0 ); -} - -/* - * Flush any data not yet written - */ -int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *buf, i; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); - - if( ssl->f_send == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " - "or mbedtls_ssl_set_bio()" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* Avoid incrementing counter if data is flushed */ - if( ssl->out_left == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); - return( 0 ); - } - - while( ssl->out_left > 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", - mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); - - buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) + - ssl->out_msglen - ssl->out_left; - ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); - - if( ret <= 0 ) - return( ret ); - - ssl->out_left -= ret; - } - - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); - - return( 0 ); -} - -/* - * Functions to handle the DTLS retransmission state machine - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * Append current handshake message to current outgoing flight - */ -static int ssl_flight_append( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_flight_item *msg; - - /* Allocate space for current message */ - if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", - sizeof( mbedtls_ssl_flight_item ) ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); - mbedtls_free( msg ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Copy current handshake message with headers */ - memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); - msg->len = ssl->out_msglen; - msg->type = ssl->out_msgtype; - msg->next = NULL; - - /* Append to the current flight */ - if( ssl->handshake->flight == NULL ) - ssl->handshake->flight = msg; - else - { - mbedtls_ssl_flight_item *cur = ssl->handshake->flight; - while( cur->next != NULL ) - cur = cur->next; - cur->next = msg; - } - - return( 0 ); -} - -/* - * Free the current flight of handshake messages - */ -static void ssl_flight_free( mbedtls_ssl_flight_item *flight ) -{ - mbedtls_ssl_flight_item *cur = flight; - mbedtls_ssl_flight_item *next; - - while( cur != NULL ) - { - next = cur->next; - - mbedtls_free( cur->p ); - mbedtls_free( cur ); - - cur = next; - } -} - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); -#endif - -/* - * Swap transform_out and out_ctr with the alternative ones - */ -static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_transform *tmp_transform; - unsigned char tmp_out_ctr[8]; - - if( ssl->transform_out == ssl->handshake->alt_transform_out ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); - - /* Swap transforms */ - tmp_transform = ssl->transform_out; - ssl->transform_out = ssl->handshake->alt_transform_out; - ssl->handshake->alt_transform_out = tmp_transform; - - /* Swap epoch + sequence_number */ - memcpy( tmp_out_ctr, ssl->out_ctr, 8 ); - memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); - memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); - - /* Adjust to the newly activated transform */ - if( ssl->transform_out != NULL && - ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_activate != NULL ) - { - if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif -} - -/* - * Retransmit the current flight of messages. - * - * Need to remember the current message in case flush_output returns - * WANT_WRITE, causing us to exit this function and come back later. - * This function must be called until state is no longer SENDING. - */ -int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) -{ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); - - if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) ); - - ssl->handshake->cur_msg = ssl->handshake->flight; - ssl_swap_epochs( ssl ); - - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; - } - - while( ssl->handshake->cur_msg != NULL ) - { - int ret; - mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg; - - /* Swap epochs before sending Finished: we can't do it after - * sending ChangeCipherSpec, in case write returns WANT_READ. - * Must be done before copying, may change out_msg pointer */ - if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && - cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) - { - ssl_swap_epochs( ssl ); - } - - memcpy( ssl->out_msg, cur->p, cur->len ); - ssl->out_msglen = cur->len; - ssl->out_msgtype = cur->type; - - ssl->handshake->cur_msg = cur->next; - - MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 ); - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - } - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - else - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; - ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); - - return( 0 ); -} - -/* - * To be called when the last message of an incoming flight is received. - */ -void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) -{ - /* We won't need to resend that one any more */ - ssl_flight_free( ssl->handshake->flight ); - ssl->handshake->flight = NULL; - ssl->handshake->cur_msg = NULL; - - /* The next incoming flight will start with this msg_seq */ - ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; - - /* Cancel timer */ - ssl_set_timer( ssl, 0 ); - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - } - else - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; -} - -/* - * To be called when the last message of an outgoing flight is send. - */ -void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) -{ - ssl_reset_retransmit_timeout( ssl ); - ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - } - else - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -/* - * Record layer functions - */ - -/* - * Write current record. - * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg. - */ -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) -{ - int ret, done = 0, out_msg_type; - size_t len = ssl->out_msglen; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - ; /* Skip special handshake treatment when resending */ - } - else -#endif - if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - out_msg_type = ssl->out_msg[0]; - - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST && - ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); - ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); - ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); - - /* - * DTLS has additional fields in the Handshake layer, - * between the length field and the actual payload: - * uint16 message_seq; - * uint24 fragment_offset; - * uint24 fragment_length; - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Make room for the additional DTLS fields */ - memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); - ssl->out_msglen += 8; - len += 8; - - /* Write message_seq and update it, except for HelloRequest */ - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) - { - ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; - ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; - ++( ssl->handshake->out_msg_seq ); - } - else - { - ssl->out_msg[4] = 0; - ssl->out_msg[5] = 0; - } - - /* We don't fragment, so frag_offset = 0 and frag_len = len */ - memset( ssl->out_msg + 6, 0x00, 3 ); - memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) - ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); - } - - /* Save handshake and CCS messages for resending */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING && - ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || - ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) - { - if( ( ret = ssl_flight_append( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); - return( ret ); - } - } -#endif - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->transform_out != NULL && - ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); - return( ret ); - } - - len = ssl->out_msglen; - } -#endif /*MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_write != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); - - ret = mbedtls_ssl_hw_record_write( ssl ); - if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - if( ret == 0 ) - done = 1; - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - if( !done ) - { - ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, ssl->out_hdr + 1 ); - - ssl->out_len[0] = (unsigned char)( len >> 8 ); - ssl->out_len[1] = (unsigned char)( len ); - - if( ssl->transform_out != NULL ) - { - if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); - return( ret ); - } - - len = ssl->out_msglen; - ssl->out_len[0] = (unsigned char)( len >> 8 ); - ssl->out_len[1] = (unsigned char)( len ); - } - - ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], - ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", - ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); - } - - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * Mark bits in bitmask (used for DTLS HS reassembly) - */ -static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) -{ - unsigned int start_bits, end_bits; - - start_bits = 8 - ( offset % 8 ); - if( start_bits != 8 ) - { - size_t first_byte_idx = offset / 8; - - /* Special case */ - if( len <= start_bits ) - { - for( ; len != 0; len-- ) - mask[first_byte_idx] |= 1 << ( start_bits - len ); - - /* Avoid potential issues with offset or len becoming invalid */ - return; - } - - offset += start_bits; /* Now offset % 8 == 0 */ - len -= start_bits; - - for( ; start_bits != 0; start_bits-- ) - mask[first_byte_idx] |= 1 << ( start_bits - 1 ); - } - - end_bits = len % 8; - if( end_bits != 0 ) - { - size_t last_byte_idx = ( offset + len ) / 8; - - len -= end_bits; /* Now len % 8 == 0 */ - - for( ; end_bits != 0; end_bits-- ) - mask[last_byte_idx] |= 1 << ( 8 - end_bits ); - } - - memset( mask + offset / 8, 0xFF, len / 8 ); -} - -/* - * Check that bitmask is full - */ -static int ssl_bitmask_check( unsigned char *mask, size_t len ) -{ - size_t i; - - for( i = 0; i < len / 8; i++ ) - if( mask[i] != 0xFF ) - return( -1 ); - - for( i = 0; i < len % 8; i++ ) - if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) - return( -1 ); - - return( 0 ); -} - -/* - * Reassemble fragmented DTLS handshake messages. - * - * Use a temporary buffer for reassembly, divided in two parts: - * - the first holds the reassembled message (including handshake header), - * - the second holds a bitmask indicating which parts of the message - * (excluding headers) have been received so far. - */ -static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) -{ - unsigned char *msg, *bitmask; - size_t frag_len, frag_off; - size_t msg_len = ssl->in_hslen - 12; /* Without headers */ - - if( ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* - * For first fragment, check size and allocate buffer - */ - if( ssl->handshake->hs_msg == NULL ) - { - size_t alloc_len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", - msg_len ) ); - - if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* The bitmask needs one bit per byte of message excluding header */ - alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); - - ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); - if( ssl->handshake->hs_msg == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Prepare final header: copy msg_type, length and message_seq, - * then add standardised fragment_offset and fragment_length */ - memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); - memset( ssl->handshake->hs_msg + 6, 0, 3 ); - memcpy( ssl->handshake->hs_msg + 9, - ssl->handshake->hs_msg + 1, 3 ); - } - else - { - /* Make sure msg_type and length are consistent */ - if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - - msg = ssl->handshake->hs_msg + 12; - bitmask = msg + msg_len; - - /* - * Check and copy current fragment - */ - frag_off = ( ssl->in_msg[6] << 16 ) | - ( ssl->in_msg[7] << 8 ) | - ssl->in_msg[8]; - frag_len = ( ssl->in_msg[9] << 16 ) | - ( ssl->in_msg[10] << 8 ) | - ssl->in_msg[11]; - - if( frag_off + frag_len > msg_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", - frag_off, frag_len, msg_len ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( frag_len + 12 > ssl->in_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", - frag_len, ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", - frag_off, frag_len ) ); - - memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); - ssl_bitmask_set( bitmask, frag_off, frag_len ); - - /* - * Do we have the complete message by now? - * If yes, finalize it, else ask to read the next record. - */ - if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); - - if( frag_len + 12 < ssl->in_msglen ) - { - /* - * We'got more handshake messages in the same record. - * This case is not handled now because no know implementation does - * that and it's hard to test, so we prefer to fail cleanly for now. - */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - if( ssl->in_left > ssl->next_record_offset ) - { - /* - * We've got more data in the buffer after the current record, - * that we don't want to overwrite. Move it before writing the - * reassembled message, and adjust in_left and next_record_offset. - */ - unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; - unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; - size_t remain_len = ssl->in_left - ssl->next_record_offset; - - /* First compute and check new lengths */ - ssl->next_record_offset = new_remain - ssl->in_hdr; - ssl->in_left = ssl->next_record_offset + remain_len; - - if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - - (size_t)( ssl->in_hdr - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - memmove( new_remain, cur_remain, remain_len ); - } - - memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); - - mbedtls_free( ssl->handshake->hs_msg ); - ssl->handshake->hs_msg = NULL; - - MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", - ssl->in_msg, ssl->in_hslen ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) -{ - if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", - ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ( - ( ssl->in_msg[1] << 16 ) | - ( ssl->in_msg[2] << 8 ) | - ssl->in_msg[3] ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" - " %d, type = %d, hslen = %d", - ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - int ret; - unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - - /* ssl->handshake is NULL when receiving ClientHello for renego */ - if( ssl->handshake != NULL && - recv_msg_seq != ssl->handshake->in_msg_seq ) - { - /* Retransmit only on last message from previous flight, to avoid - * too many retransmissions. - * Besides, No sane server ever retransmits HelloVerifyRequest */ - if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && - ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " - "message_seq = %d, start_of_flight = %d", - recv_msg_seq, - ssl->handshake->in_flight_start_seq ) ); - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " - "message_seq = %d, expected = %d", - recv_msg_seq, - ssl->handshake->in_msg_seq ) ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - /* Wait until message completion to increment in_msg_seq */ - - /* Reassemble if current message is fragmented or reassembly is - * already in progress */ - if( ssl->in_msglen < ssl->in_hslen || - memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || - memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 || - ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); - - if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); - return( ret ); - } - } - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - /* With TLS we don't handle fragmentation (for now) */ - if( ssl->in_msglen < ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - return( 0 ); -} - -void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) -{ - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && - ssl->handshake != NULL ) - { - ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); - } - - /* Handshake message is complete, increment counter */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL ) - { - ssl->handshake->in_msg_seq++; - } -#endif -} - -/* - * DTLS anti-replay: RFC 6347 4.1.2.6 - * - * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). - * Bit n is set iff record number in_window_top - n has been seen. - * - * Usually, in_window_top is the last record number seen and the lsb of - * in_window is set. The only exception is the initial state (record number 0 - * not seen yet). - */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) -{ - ssl->in_window_top = 0; - ssl->in_window = 0; -} - -static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) -{ - return( ( (uint64_t) buf[0] << 40 ) | - ( (uint64_t) buf[1] << 32 ) | - ( (uint64_t) buf[2] << 24 ) | - ( (uint64_t) buf[3] << 16 ) | - ( (uint64_t) buf[4] << 8 ) | - ( (uint64_t) buf[5] ) ); -} - -/* - * Return 0 if sequence number is acceptable, -1 otherwise - */ -int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ) -{ - uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); - uint64_t bit; - - if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) - return( 0 ); - - if( rec_seqnum > ssl->in_window_top ) - return( 0 ); - - bit = ssl->in_window_top - rec_seqnum; - - if( bit >= 64 ) - return( -1 ); - - if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) - return( -1 ); - - return( 0 ); -} - -/* - * Update replay window on new validated record - */ -void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) -{ - uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); - - if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) - return; - - if( rec_seqnum > ssl->in_window_top ) - { - /* Update window_top and the contents of the window */ - uint64_t shift = rec_seqnum - ssl->in_window_top; - - if( shift >= 64 ) - ssl->in_window = 1; - else - { - ssl->in_window <<= shift; - ssl->in_window |= 1; - } - - ssl->in_window_top = rec_seqnum; - } - else - { - /* Mark that number as seen in the current window */ - uint64_t bit = ssl->in_window_top - rec_seqnum; - - if( bit < 64 ) /* Always true, but be extra sure */ - ssl->in_window |= (uint64_t) 1 << bit; - } -} -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) -/* Forward declaration */ -static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); - -/* - * Without any SSL context, check if a datagram looks like a ClientHello with - * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. - * Both input and output include full DTLS headers. - * - * - if cookie is valid, return 0 - * - if ClientHello looks superficially valid but cookie is not, - * fill obuf and set olen, then - * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED - * - otherwise return a specific error code - */ -static int ssl_check_dtls_clihlo_cookie( - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie, - const unsigned char *cli_id, size_t cli_id_len, - const unsigned char *in, size_t in_len, - unsigned char *obuf, size_t buf_len, size_t *olen ) -{ - size_t sid_len, cookie_len; - unsigned char *p; - - if( f_cookie_write == NULL || f_cookie_check == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* - * Structure of ClientHello with record and handshake headers, - * and expected values. We don't need to check a lot, more checks will be - * done when actually parsing the ClientHello - skipping those checks - * avoids code duplication and does not make cookie forging any easier. - * - * 0-0 ContentType type; copied, must be handshake - * 1-2 ProtocolVersion version; copied - * 3-4 uint16 epoch; copied, must be 0 - * 5-10 uint48 sequence_number; copied - * 11-12 uint16 length; (ignored) - * - * 13-13 HandshakeType msg_type; (ignored) - * 14-16 uint24 length; (ignored) - * 17-18 uint16 message_seq; copied - * 19-21 uint24 fragment_offset; copied, must be 0 - * 22-24 uint24 fragment_length; (ignored) - * - * 25-26 ProtocolVersion client_version; (ignored) - * 27-58 Random random; (ignored) - * 59-xx SessionID session_id; 1 byte len + sid_len content - * 60+ opaque cookie<0..2^8-1>; 1 byte len + content - * ... - * - * Minimum length is 61 bytes. - */ - if( in_len < 61 || - in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || - in[3] != 0 || in[4] != 0 || - in[19] != 0 || in[20] != 0 || in[21] != 0 ) - { - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - sid_len = in[59]; - if( sid_len > in_len - 61 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - cookie_len = in[60 + sid_len]; - if( cookie_len > in_len - 60 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, - cli_id, cli_id_len ) == 0 ) - { - /* Valid cookie */ - return( 0 ); - } - - /* - * If we get here, we've got an invalid cookie, let's prepare HVR. - * - * 0-0 ContentType type; copied - * 1-2 ProtocolVersion version; copied - * 3-4 uint16 epoch; copied - * 5-10 uint48 sequence_number; copied - * 11-12 uint16 length; olen - 13 - * - * 13-13 HandshakeType msg_type; hello_verify_request - * 14-16 uint24 length; olen - 25 - * 17-18 uint16 message_seq; copied - * 19-21 uint24 fragment_offset; copied - * 22-24 uint24 fragment_length; olen - 25 - * - * 25-26 ProtocolVersion server_version; 0xfe 0xff - * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie - * - * Minimum length is 28. - */ - if( buf_len < 28 ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - /* Copy most fields and adapt others */ - memcpy( obuf, in, 25 ); - obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; - obuf[25] = 0xfe; - obuf[26] = 0xff; - - /* Generate and write actual cookie */ - p = obuf + 28; - if( f_cookie_write( p_cookie, - &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) - { - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - *olen = p - obuf; - - /* Go back and fill length fields */ - obuf[27] = (unsigned char)( *olen - 28 ); - - obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); - obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); - obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); - - obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); - obuf[12] = (unsigned char)( ( *olen - 13 ) ); - - return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); -} - -/* - * Handle possible client reconnect with the same UDP quadruplet - * (RFC 6347 Section 4.2.8). - * - * Called by ssl_parse_record_header() in case we receive an epoch 0 record - * that looks like a ClientHello. - * - * - if the input looks like a ClientHello without cookies, - * send back HelloVerifyRequest, then - * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED - * - if the input looks like a ClientHello with a valid cookie, - * reset the session of the current context, and - * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT - * - if anything goes wrong, return a specific error code - * - * mbedtls_ssl_read_record() will ignore the record if anything else than - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function - * cannot not return 0. - */ -static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t len; - - ret = ssl_check_dtls_clihlo_cookie( - ssl->conf->f_cookie_write, - ssl->conf->f_cookie_check, - ssl->conf->p_cookie, - ssl->cli_id, ssl->cli_id_len, - ssl->in_buf, ssl->in_left, - ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); - - if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) - { - /* Don't check write errors as we can't do anything here. - * If the error is permanent we'll catch it later, - * if it's not, then hopefully it'll work next time. */ - (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); - - return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); - } - - if( ret == 0 ) - { - /* Got a valid cookie, partially reset context */ - if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); - } - - return( ret ); -} -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ - -/* - * ContentType type; - * ProtocolVersion version; - * uint16 epoch; // DTLS only - * uint48 sequence_number; // DTLS only - * uint16 length; - * - * Return 0 if header looks sane (and, for DTLS, the record is expected) - * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, - * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. - * - * With DTLS, mbedtls_ssl_read_record() will: - * 1. proceed with the record if this function returns 0 - * 2. drop only the current record if this function returns UNEXPECTED_RECORD - * 3. return CLIENT_RECONNECT if this function return that value - * 4. drop the whole datagram if this function returns anything else. - * Point 2 is needed when the peer is resending, and we have already received - * the first record from a datagram but are still waiting for the others. - */ -static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) -{ - int ret; - int major_ver, minor_ver; - - MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); - - ssl->in_msgtype = ssl->in_hdr[0]; - ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; - mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->in_msgtype, - major_ver, minor_ver, ssl->in_msglen ) ); - - /* Check record type */ - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msgtype != MBEDTLS_SSL_MSG_ALERT && - ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && - ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); - - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) - { - return( ret ); - } - - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* Check version */ - if( major_ver != ssl->major_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( minor_ver > ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* Check length against the size of our buffer */ - if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN - - (size_t)( ssl->in_msg - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* Check length against bounds of the current transform and version */ - if( ssl->transform_in == NULL ) - { - if( ssl->in_msglen < 1 || - ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - else - { - if( ssl->in_msglen < ssl->transform_in->minlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * TLS encrypted messages can have up to 256 bytes of padding - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && - ssl->in_msglen > ssl->transform_in->minlen + - MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif - } - - /* - * DTLS-related tests done last, because most of them may result in - * silently dropping the record (but not the whole datagram), and we only - * want to consider that after ensuring that the "basic" fields (type, - * version, length) are sane. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; - - /* Drop unexpected ChangeCipherSpec messages */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - - /* Drop unexpected ApplicationData records, - * except at the beginning of renegotiations */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && - ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->state == MBEDTLS_SSL_SERVER_HELLO ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - - /* Check epoch (and sequence number) with DTLS */ - if( rec_epoch != ssl->in_epoch ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " - "expected %d, received %d", - ssl->in_epoch, rec_epoch ) ); - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) - /* - * Check for an epoch 0 ClientHello. We can't use in_msg here to - * access the first byte of record content (handshake type), as we - * have an active transform (possibly iv_len != 0), so use the - * fact that the record header len is 13 instead. - */ - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && - rec_epoch == 0 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_left > 13 && - ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " - "from the same port" ) ); - return( ssl_handle_possible_reconnect( ssl ) ); - } - else -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - /* Replay detection only works for the current epoch */ - if( rec_epoch == ssl->in_epoch && - mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } -#endif - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - return( 0 ); -} - -/* - * If applicable, decrypt (and decompress) record content - */ -static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) -{ - int ret, done = 0; - - MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", - ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ); - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_read != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); - - ret = mbedtls_ssl_hw_record_read( ssl ); - if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - if( ret == 0 ) - done = 1; - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - if( !done && ssl->transform_in != NULL ) - { - if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", - ssl->in_msg, ssl->in_msglen ); - - if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->transform_in != NULL && - ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - mbedtls_ssl_dtls_replay_update( ssl ); - } -#endif - - return( 0 ); -} - -static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); - -/* - * Read a record. - * - * Silently ignore non-fatal alert (and for DTLS, invalid records as well, - * RFC 6347 4.1.2.7) and continue reading until a valid record is found. - * - */ -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); - - do { - - if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); - return( ret ); - } - - ret = mbedtls_ssl_handle_message_type( ssl ); - - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); - - if( 0 != ret ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); - return( ret ); - } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - mbedtls_ssl_update_handshake_status( ssl ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); - - return( 0 ); -} - -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) -{ - int ret; - - if( ssl->in_hslen != 0 && ssl->in_hslen < ssl->in_msglen ) - { - /* - * Get next Handshake message in the current record - */ - ssl->in_msglen -= ssl->in_hslen; - - memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, - ssl->in_msglen ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", - ssl->in_msg, ssl->in_msglen ); - - return( 0 ); - } - - ssl->in_hslen = 0; - - /* - * Read the record header and parse it - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) -read_record_header: -#endif - - if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - if( ( ret = ssl_parse_record_header( ssl ) ) != 0 ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) - { - if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) - { - /* Skip unexpected record (but not whole datagram) */ - ssl->next_record_offset = ssl->in_msglen - + mbedtls_ssl_hdr_len( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " - "(header)" ) ); - } - else - { - /* Skip invalid record and the rest of the datagram */ - ssl->next_record_offset = 0; - ssl->in_left = 0; - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " - "(header)" ) ); - } - - /* Get next record */ - goto read_record_header; - } -#endif - return( ret ); - } - - /* - * Read and optionally decrypt the message contents - */ - if( ( ret = mbedtls_ssl_fetch_input( ssl, - mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - /* Done reading this record, get ready for the next one */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); - else -#endif - ssl->in_left = 0; - - if( ( ret = ssl_prepare_record_content( ssl ) ) != 0 ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Silently discard invalid records */ - if( ret == MBEDTLS_ERR_SSL_INVALID_RECORD || - ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - /* Except when waiting for Finished as a bad mac here - * probably means something went wrong in the handshake - * (eg wrong psk used, mitm downgrade attempt, etc.) */ - if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || - ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) - { -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); - } -#endif - return( ret ); - } - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - if( ssl->conf->badmac_limit != 0 && - ++ssl->badmac_seen >= ssl->conf->badmac_limit ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } -#endif - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); - goto read_record_header; - } - - return( ret ); - } - else -#endif - { - /* Error out (and send alert) on invalid records */ -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); - } -#endif - return( ret ); - } - } - - /* - * When we sent the last flight of the handshake, we MUST respond to a - * retransmit of the peer's previous flight with a retransmit. (In - * practice, only the Finished message will make it, other messages - * including CCS use the old transform so they're dropped as invalid.) - * - * If the record we received is not a handshake message, however, it - * means the peer received our last flight so we can clean up - * handshake info. - * - * This check needs to be done before prepare_handshake() due to an edge - * case: if the client immediately requests renegotiation, this - * finishes the current handshake first, avoiding the new ClientHello - * being mistaken for an ancient message in the current handshake. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) ); - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - else - { - ssl_handshake_wrapup_free_hs_transform( ssl ); - } - } -#endif - - return( 0 ); -} - -int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) -{ - int ret; - - /* - * Handle particular types of records - */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) - { - return( ret ); - } - } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", - ssl->in_msg[0], ssl->in_msg[1] ) ); - - /* - * Ignore non-fatal alerts, except close_notify and no_renegotiation - */ - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", - ssl->in_msg[1] ) ); - return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); - } - - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); - return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); - /* Will be handled when trying to parse ServerHello */ - return( 0 ); - } -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); - /* Will be handled in mbedtls_ssl_parse_certificate() */ - return( 0 ); - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ - - /* Silently ignore: fetch new message */ - return MBEDTLS_ERR_SSL_NON_FATAL; - } - - return( 0 ); -} - -int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) -{ - int ret; - - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} - -int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, - unsigned char level, - unsigned char message ) -{ - int ret; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); - - ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; - ssl->out_msglen = 2; - ssl->out_msg[0] = level; - ssl->out_msg[1] = message; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); - - return( 0 ); -} - -/* - * Handshake functions - */ -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} - -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, n; - const mbedtls_x509_crt *crt; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - if( ssl->client_auth == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* - * If using SSLv3 and got no cert, send an Alert message - * (otherwise an empty Certificate message will be sent). - */ - if( mbedtls_ssl_own_cert( ssl ) == NULL && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl->out_msglen = 2; - ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; - ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; - ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); - goto write_msg; - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - } -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - { - if( mbedtls_ssl_own_cert( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); - return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); - } - } -#endif - - MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 6 length of all certs - * 7 . 9 length of cert. 1 - * 10 . n-1 peer certificate - * n . n+2 length of cert. 2 - * n+3 . ... upper level cert, etc. - */ - i = 7; - crt = mbedtls_ssl_own_cert( ssl ); - - while( crt != NULL ) - { - n = crt->raw.len; - if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", - i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) ); - return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); - } - - ssl->out_msg[i ] = (unsigned char)( n >> 16 ); - ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); - ssl->out_msg[i + 2] = (unsigned char)( n ); - - i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); - i += n; crt = crt->next; - } - - ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); - ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); - ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); - - ssl->out_msglen = i; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) -write_msg: -#endif - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); - - return( ret ); -} - -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, n; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - int authmode = ssl->conf->authmode; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) - authmode = ssl->handshake->sni_authmode; -#endif - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - authmode == MBEDTLS_SSL_VERIFY_NONE ) - { - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } -#endif - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - ssl->state++; - -#if defined(MBEDTLS_SSL_SRV_C) -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* - * Check if the client sent an empty certificate - */ - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( ssl->in_msglen == 2 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && - ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); - - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); - } - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && - ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && - memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); - - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); - } - } -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ -#endif /* MBEDTLS_SSL_SRV_C */ - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || - ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - i = mbedtls_ssl_hs_hdr_len( ssl ); - - /* - * Same message structure as in mbedtls_ssl_write_certificate() - */ - n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; - - if( ssl->in_msg[i] != 0 || - ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - /* In case we tried to reuse a session but it failed */ - if( ssl->session_negotiate->peer_cert != NULL ) - { - mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); - mbedtls_free( ssl->session_negotiate->peer_cert ); - } - - if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, - sizeof( mbedtls_x509_crt ) ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - sizeof( mbedtls_x509_crt ) ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); - - i += 3; - - while( i < ssl->in_hslen ) - { - if( ssl->in_msg[i] != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) - | (unsigned int) ssl->in_msg[i + 2]; - i += 3; - - if( n < 128 || i + n > ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, - ssl->in_msg + i, n ); - if( 0 != ret && ( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND ) != ret ) - { - MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); - return( ret ); - } - - i += n; - } - - MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); - - /* - * On client, make sure the server cert doesn't change during renego to - * avoid "triple handshake" attack: https://secure-resumption.com/ - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - if( ssl->session->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - if( ssl->session->peer_cert->raw.len != - ssl->session_negotiate->peer_cert->raw.len || - memcmp( ssl->session->peer_cert->raw.p, - ssl->session_negotiate->peer_cert->raw.p, - ssl->session->peer_cert->raw.len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - } -#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ - - if( authmode != MBEDTLS_SSL_VERIFY_NONE ) - { - mbedtls_x509_crt *ca_chain; - mbedtls_x509_crl *ca_crl; - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_ca_chain != NULL ) - { - ca_chain = ssl->handshake->sni_ca_chain; - ca_crl = ssl->handshake->sni_ca_crl; - } - else -#endif - { - ca_chain = ssl->conf->ca_chain; - ca_crl = ssl->conf->ca_crl; - } - - if( ca_chain == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); - return( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED ); - } - - /* - * Main check: verify certificate - */ - ret = mbedtls_x509_crt_verify_with_profile( - ssl->session_negotiate->peer_cert, - ca_chain, ca_crl, - ssl->conf->cert_profile, - ssl->hostname, - &ssl->session_negotiate->verify_result, - ssl->conf->f_vrfy, ssl->conf->p_vrfy ); - - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); - } - - /* - * Secondary checks: always done, but change 'ret' only if it was 0 - */ - -#if defined(MBEDTLS_ECP_C) - { - const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk; - - /* If certificate uses an EC key, make sure the curve is OK */ - if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && - mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); - if( ret == 0 ) - ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } - } -#endif /* MBEDTLS_ECP_C */ - - if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, - ciphersuite_info, - ! ssl->conf->endpoint, - &ssl->session_negotiate->verify_result ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); - if( ret == 0 ) - ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } - - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - ret = 0; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); - - return( ret ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); - - ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; - ssl->out_msglen = 1; - ssl->out_msg[0] = 1; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); - - return( 0 ); -} - -int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); - } - - /* - * Switch to our negotiated transform and session parameters for inbound - * data. - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); - ssl->transform_in = ssl->transform_negotiate; - ssl->session_in = ssl->session_negotiate; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - ssl_dtls_replay_reset( ssl ); -#endif - - /* Increment epoch */ - if( ++ssl->in_epoch == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset( ssl->in_ctr, 0, 8 ); - - /* - * Set the in_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->in_msg = ssl->in_iv; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_activate != NULL ) - { - if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif - - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); - - return( 0 ); -} - -void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) -{ - ((void) ciphersuite_info); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) - ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) - if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - ssl->handshake->update_checksum = ssl_update_checksum_sha384; - else -#endif -#if defined(MBEDTLS_SHA256_C) - if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) - ssl->handshake->update_checksum = ssl_update_checksum_sha256; - else -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return; - } -} - -void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_starts( &ssl->handshake->fin_md5 ); - mbedtls_sha1_starts( &ssl->handshake->fin_sha1 ); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_SHA256_ALT) - mbedtls_sha256_free_alt( &ssl->handshake->fin_sha256); - mbedtls_sha256_init_alt( &ssl->handshake->fin_sha256); - mbedtls_sha256_starts_alt( &ssl->handshake->fin_sha256, 0 ); -#else - mbedtls_sha256_starts( &ssl->handshake->fin_sha256, 0 ); -#endif -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_starts( &ssl->handshake->fin_sha512, 1 ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -} - -static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_update( &ssl->handshake->fin_md5 , buf, len ); - mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_SHA256_ALT) - mbedtls_sha256_update_alt( &ssl->handshake->fin_sha256, buf, len ); -#else - mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); -#endif -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -} - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - mbedtls_md5_update( &ssl->handshake->fin_md5 , buf, len ); - mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); -} -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_SHA256_ALT) -static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - mbedtls_sha256_update_alt( &ssl->handshake->fin_sha256, buf, len ); -} -#else -static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); -} -#endif -#endif - -#if defined(MBEDTLS_SHA512_C) -static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); -} -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -static void ssl_calc_finished_ssl( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - const char *sender; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - - unsigned char padbuf[48]; - unsigned char md5sum[16]; - unsigned char sha1sum[20]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); - mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - - /* - * SSLv3: - * hash = - * MD5( master + pad2 + - * MD5( handshake + sender + master + pad1 ) ) - * + SHA1( master + pad2 + - * SHA1( handshake + sender + master + pad1 ) ) - */ - -#if !defined(MBEDTLS_MD5_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) - md5.state, sizeof( md5.state ) ); -#endif - -#if !defined(MBEDTLS_SHA1_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof( sha1.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT" - : "SRVR"; - - memset( padbuf, 0x36, 48 ); - - mbedtls_md5_update( &md5, (const unsigned char *) sender, 4 ); - mbedtls_md5_update( &md5, session->master, 48 ); - mbedtls_md5_update( &md5, padbuf, 48 ); - mbedtls_md5_finish( &md5, md5sum ); - - mbedtls_sha1_update( &sha1, (const unsigned char *) sender, 4 ); - mbedtls_sha1_update( &sha1, session->master, 48 ); - mbedtls_sha1_update( &sha1, padbuf, 40 ); - mbedtls_sha1_finish( &sha1, sha1sum ); - - memset( padbuf, 0x5C, 48 ); - - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, session->master, 48 ); - mbedtls_md5_update( &md5, padbuf, 48 ); - mbedtls_md5_update( &md5, md5sum, 16 ); - mbedtls_md5_finish( &md5, buf ); - - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, session->master, 48 ); - mbedtls_sha1_update( &sha1, padbuf , 40 ); - mbedtls_sha1_update( &sha1, sha1sum, 20 ); - mbedtls_sha1_finish( &sha1, buf + 16 ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - mbedtls_zeroize( md5sum, sizeof( md5sum ) ); - mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_calc_finished_tls( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - const char *sender; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char padbuf[36]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); - mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - - /* - * TLSv1: - * hash = PRF( master, finished_label, - * MD5( handshake ) + SHA1( handshake ) )[0..11] - */ - -#if !defined(MBEDTLS_MD5_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) - md5.state, sizeof( md5.state ) ); -#endif - -#if !defined(MBEDTLS_SHA1_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof( sha1.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) - ? "client finished" - : "server finished"; - - mbedtls_md5_finish( &md5, padbuf ); - mbedtls_sha1_finish( &sha1, padbuf + 16 ); - - ssl->handshake->tls_prf( session->master, 48, sender, - padbuf, 36, buf, len ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_SHA256_ALT) -static void ssl_calc_finished_tls_sha256( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - const char *sender; - mbedtls_sha256_context sha256; - unsigned char padbuf[32]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - mbedtls_sha256_init_alt( &sha256 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); - - mbedtls_sha256_clone_alt( &sha256, &ssl->handshake->fin_sha256 ); - - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ - -#if !defined(MBEDTLS_SHA256_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) - sha256.state, sizeof( sha256.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) - ? "client finished" - : "server finished"; - - mbedtls_sha256_finish_alt( &sha256, padbuf ); - - ssl->handshake->tls_prf( session->master, 48, sender, - padbuf, 32, buf, len ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - mbedtls_sha256_free_alt( &sha256 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} - -#else /* MBEDTLS_SHA256_ALT */ - -static void ssl_calc_finished_tls_sha256( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - const char *sender; - mbedtls_sha256_context sha256; - unsigned char padbuf[32]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - mbedtls_sha256_init( &sha256 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); - - mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); - - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ - -#if !defined(MBEDTLS_SHA256_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) - sha256.state, sizeof( sha256.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) - ? "client finished" - : "server finished"; - - mbedtls_sha256_finish( &sha256, padbuf ); - - ssl->handshake->tls_prf( session->master, 48, sender, - padbuf, 32, buf, len ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - mbedtls_sha256_free( &sha256 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} - -#endif /* MBEDTLS_SHA256_ALT */ - -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) -static void ssl_calc_finished_tls_sha384( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - const char *sender; - mbedtls_sha512_context sha512; - unsigned char padbuf[48]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - mbedtls_sha512_init( &sha512 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); - - mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); - - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ - -#if !defined(MBEDTLS_SHA512_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) - sha512.state, sizeof( sha512.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) - ? "client finished" - : "server finished"; - - mbedtls_sha512_finish( &sha512, padbuf ); - - ssl->handshake->tls_prf( session->master, 48, sender, - padbuf, 48, buf, len ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - mbedtls_sha512_free( &sha512 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) -{ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); - - /* - * Free our handshake params - */ - mbedtls_ssl_handshake_free( ssl->handshake ); - mbedtls_free( ssl->handshake ); - ssl->handshake = NULL; - - /* - * Free the previous transform and swith in the current one - */ - if( ssl->transform ) - { - mbedtls_ssl_transform_free( ssl->transform ); - mbedtls_free( ssl->transform ); - } - ssl->transform = ssl->transform_negotiate; - ssl->transform_negotiate = NULL; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); -} - -void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) -{ - int resume = ssl->handshake->resume; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; - ssl->renego_records_seen = 0; - } -#endif - - /* - * Free the previous session and switch in the current one - */ - if( ssl->session ) - { -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - /* RFC 7366 3.1: keep the EtM state */ - ssl->session_negotiate->encrypt_then_mac = - ssl->session->encrypt_then_mac; -#endif - - mbedtls_ssl_session_free( ssl->session ); - mbedtls_free( ssl->session ); - } - ssl->session = ssl->session_negotiate; - ssl->session_negotiate = NULL; - - /* - * Add cache entry - */ - if( ssl->conf->f_set_cache != NULL && - ssl->session->id_len != 0 && - resume == 0 ) - { - if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->flight != NULL ) - { - /* Cancel handshake timer */ - ssl_set_timer( ssl, 0 ); - - /* Keep last flight around in case we need to resend it: - * we need the handshake and transform structures for that */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); - } - else -#endif - ssl_handshake_wrapup_free_hs_transform( ssl ); - - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); -} - -int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) -{ - int ret, hash_len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); - - /* - * Set the out_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; - - ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); - - /* - * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites - * may define some other value. Currently (early 2016), no defined - * ciphersuite does this (and this is unlikely to change as activity has - * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. - */ - hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->verify_data_len = hash_len; - memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); -#endif - - ssl->out_msglen = 4 + hash_len; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; - - /* - * In case of session resuming, invert the client and server - * ChangeCipherSpec messages order. - */ - if( ssl->handshake->resume != 0 ) - { -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; -#endif - } - else - ssl->state++; - - /* - * Switch to our negotiated transform and session parameters for outbound - * data. - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - unsigned char i; - - /* Remember current epoch settings for resending */ - ssl->handshake->alt_transform_out = ssl->transform_out; - memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 ); - - /* Set sequence_number to zero */ - memset( ssl->out_ctr + 2, 0, 6 ); - - /* Increment epoch */ - for( i = 2; i > 0; i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset( ssl->out_ctr, 0, 8 ); - - ssl->transform_out = ssl->transform_negotiate; - ssl->session_out = ssl->session_negotiate; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_activate != NULL ) - { - if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_send_flight_completed( ssl ); -#endif - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define SSL_MAX_HASH_LEN 36 -#else -#define SSL_MAX_HASH_LEN 12 -#endif - -int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned int hash_len; - unsigned char buf[SSL_MAX_HASH_LEN]; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); - - ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* There is currently no ciphersuite using another length with TLS 1.2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - hash_len = 36; - else -#endif - hash_len = 12; - - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); - } - - if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), - buf, hash_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->verify_data_len = hash_len; - memcpy( ssl->peer_verify_data, buf, hash_len ); -#endif - - if( ssl->handshake->resume != 0 ) - { -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; -#endif - } - else - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_recv_flight_completed( ssl ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); - - return( 0 ); -} - -static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) -{ - memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_init( &handshake->fin_md5 ); - mbedtls_sha1_init( &handshake->fin_sha1 ); - mbedtls_md5_starts( &handshake->fin_md5 ); - mbedtls_sha1_starts( &handshake->fin_sha1 ); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_SHA256_ALT) - mbedtls_sha256_init_alt( &handshake->fin_sha256 ); - mbedtls_sha256_starts_alt( &handshake->fin_sha256, 0 ); -#else - mbedtls_sha256_init( &handshake->fin_sha256 ); - mbedtls_sha256_starts( &handshake->fin_sha256, 0 ); -#endif -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_init( &handshake->fin_sha512 ); - mbedtls_sha512_starts( &handshake->fin_sha512, 1 ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - handshake->update_checksum = ssl_update_checksum_start; - handshake->sig_alg = MBEDTLS_SSL_HASH_SHA1; - -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_init( &handshake->dhm_ctx ); -#endif -#if defined(MBEDTLS_ECDH_C) - mbedtls_ecdh_init( &handshake->ecdh_ctx ); -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); -#if defined(MBEDTLS_SSL_CLI_C) - handshake->ecjpake_cache = NULL; - handshake->ecjpake_cache_len = 0; -#endif -#endif - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; -#endif -} - -static void ssl_transform_init( mbedtls_ssl_transform *transform ) -{ - memset( transform, 0, sizeof(mbedtls_ssl_transform) ); - - mbedtls_cipher_init( &transform->cipher_ctx_enc ); - mbedtls_cipher_init( &transform->cipher_ctx_dec ); - - mbedtls_md_init( &transform->md_ctx_enc ); - mbedtls_md_init( &transform->md_ctx_dec ); -} - -void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) -{ - memset( session, 0, sizeof(mbedtls_ssl_session) ); -} - -static int ssl_handshake_init( mbedtls_ssl_context *ssl ) -{ - /* Clear old handshake information if present */ - if( ssl->transform_negotiate ) - mbedtls_ssl_transform_free( ssl->transform_negotiate ); - if( ssl->session_negotiate ) - mbedtls_ssl_session_free( ssl->session_negotiate ); - if( ssl->handshake ) - mbedtls_ssl_handshake_free( ssl->handshake ); - - /* - * Either the pointers are now NULL or cleared properly and can be freed. - * Now allocate missing structures. - */ - if( ssl->transform_negotiate == NULL ) - { - ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); - } - - if( ssl->session_negotiate == NULL ) - { - ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); - } - - if( ssl->handshake == NULL ) - { - ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); - } - - /* All pointers should exist and can be directly freed without issue */ - if( ssl->handshake == NULL || - ssl->transform_negotiate == NULL || - ssl->session_negotiate == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); - - mbedtls_free( ssl->handshake ); - mbedtls_free( ssl->transform_negotiate ); - mbedtls_free( ssl->session_negotiate ); - - ssl->handshake = NULL; - ssl->transform_negotiate = NULL; - ssl->session_negotiate = NULL; - - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Initialize structures */ - mbedtls_ssl_session_init( ssl->session_negotiate ); - ssl_transform_init( ssl->transform_negotiate ); - ssl_handshake_params_init( ssl->handshake ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->handshake->alt_transform_out = ssl->transform_out; - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; - else - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; - - ssl_set_timer( ssl, 0 ); - } -#endif - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) -/* Dummy cookie callbacks for defaults */ -static int ssl_cookie_write_dummy( void *ctx, - unsigned char **p, unsigned char *end, - const unsigned char *cli_id, size_t cli_id_len ) -{ - ((void) ctx); - ((void) p); - ((void) end); - ((void) cli_id); - ((void) cli_id_len); - - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); -} - -static int ssl_cookie_check_dummy( void *ctx, - const unsigned char *cookie, size_t cookie_len, - const unsigned char *cli_id, size_t cli_id_len ) -{ - ((void) ctx); - ((void) cookie); - ((void) cookie_len); - ((void) cli_id); - ((void) cli_id_len); - - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); -} -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ - -/* - * Initialize an SSL context - */ -void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) -{ - memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); -} - -/* - * Setup an SSL context - */ -int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, - const mbedtls_ssl_config *conf ) -{ - int ret; - const size_t len = MBEDTLS_SSL_BUFFER_LEN; - - ssl->conf = conf; - - /* - * Prepare base structures - */ - if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || - ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); - mbedtls_free( ssl->in_buf ); - ssl->in_buf = NULL; - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->out_hdr = ssl->out_buf; - ssl->out_ctr = ssl->out_buf + 3; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - - ssl->in_hdr = ssl->in_buf; - ssl->in_ctr = ssl->in_buf + 3; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; - } - else -#endif - { - ssl->out_ctr = ssl->out_buf; - ssl->out_hdr = ssl->out_buf + 8; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - - ssl->in_ctr = ssl->in_buf; - ssl->in_hdr = ssl->in_buf + 8; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; - } - - if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Reset an initialized and used SSL context for re-use while retaining - * all application-set variables, function pointers and data. - * - * If partial is non-zero, keep data in the input buffer and client ID. - * (Use when a DTLS client reconnects from the same port.) - */ -static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) -{ - int ret; - - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; - - /* Cancel any possibly running timer */ - ssl_set_timer( ssl, 0 ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; - ssl->renego_records_seen = 0; - - ssl->verify_data_len = 0; - memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); - memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); -#endif - ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; - - ssl->in_offt = NULL; - - ssl->in_msg = ssl->in_buf + 13; - ssl->in_msgtype = 0; - ssl->in_msglen = 0; - if( partial == 0 ) - ssl->in_left = 0; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - ssl->next_record_offset = 0; - ssl->in_epoch = 0; -#endif -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - ssl_dtls_replay_reset( ssl ); -#endif - - ssl->in_hslen = 0; - ssl->nb_zero = 0; - ssl->record_read = 0; - - ssl->out_msg = ssl->out_buf + 13; - ssl->out_msgtype = 0; - ssl->out_msglen = 0; - ssl->out_left = 0; -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) - ssl->split_done = 0; -#endif - - ssl->transform_in = NULL; - ssl->transform_out = NULL; - - memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); - if( partial == 0 ) - memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_reset != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); - if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif - - if( ssl->transform ) - { - mbedtls_ssl_transform_free( ssl->transform ); - mbedtls_free( ssl->transform ); - ssl->transform = NULL; - } - - if( ssl->session ) - { - mbedtls_ssl_session_free( ssl->session ); - mbedtls_free( ssl->session ); - ssl->session = NULL; - } - -#if defined(MBEDTLS_SSL_ALPN) - ssl->alpn_chosen = NULL; -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - if( partial == 0 ) - { - mbedtls_free( ssl->cli_id ); - ssl->cli_id = NULL; - ssl->cli_id_len = 0; - } -#endif - - if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Reset an initialized and used SSL context for re-use while retaining - * all application-set variables, function pointers and data. - */ -int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) -{ - return( ssl_session_reset_int( ssl, 0 ) ); -} - -/* - * SSL set accessors - */ -void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) -{ - conf->endpoint = endpoint; -} - -void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) -{ - conf->transport = transport; -} - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) -{ - conf->anti_replay = mode; -} -#endif - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) -void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) -{ - conf->badmac_limit = limit; -} -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) -{ - conf->hs_timeout_min = min; - conf->hs_timeout_max = max; -} -#endif - -void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) -{ - conf->authmode = authmode; -} - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - conf->f_vrfy = f_vrfy; - conf->p_vrfy = p_vrfy; -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - conf->f_rng = f_rng; - conf->p_rng = p_rng; -} - -void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, - void (*f_dbg)(void *, int, const char *, int, const char *), - void *p_dbg ) -{ - conf->f_dbg = f_dbg; - conf->p_dbg = p_dbg; -} - -void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, - void *p_bio, - mbedtls_ssl_send_t *f_send, - mbedtls_ssl_recv_t *f_recv, - mbedtls_ssl_recv_timeout_t *f_recv_timeout ) -{ - ssl->p_bio = p_bio; - ssl->f_send = f_send; - ssl->f_recv = f_recv; - ssl->f_recv_timeout = f_recv_timeout; -} - -void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) -{ - conf->read_timeout = timeout; -} - -void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, - void *p_timer, - mbedtls_ssl_set_timer_t *f_set_timer, - mbedtls_ssl_get_timer_t *f_get_timer ) -{ - ssl->p_timer = p_timer; - ssl->f_set_timer = f_set_timer; - ssl->f_get_timer = f_get_timer; - - /* Make sure we start with no timer running */ - ssl_set_timer( ssl, 0 ); -} - -#if defined(MBEDTLS_SSL_SRV_C) -void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, - void *p_cache, - int (*f_get_cache)(void *, mbedtls_ssl_session *), - int (*f_set_cache)(void *, const mbedtls_ssl_session *) ) -{ - conf->p_cache = p_cache; - conf->f_get_cache = f_get_cache; - conf->f_set_cache = f_set_cache; -} -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_CLI_C) -int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) -{ - int ret; - - if( ssl == NULL || - session == NULL || - ssl->session_negotiate == NULL || - ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) - return( ret ); - - ssl->handshake->resume = 1; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_CLI_C */ - -void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, - const int *ciphersuites ) -{ - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; -} - -void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, - const int *ciphersuites, - int major, int minor ) -{ - if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) - return; - - if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) - return; - - conf->ciphersuite_list[minor] = ciphersuites; -} - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, - const mbedtls_x509_crt_profile *profile ) -{ - conf->cert_profile = profile; -} - -/* Append a new keycert entry to a (possibly empty) list */ -static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, - mbedtls_x509_crt *cert, - mbedtls_pk_context *key ) -{ - mbedtls_ssl_key_cert *new; - - new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); - if( new == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - new->cert = cert; - new->key = key; - new->next = NULL; - - /* Update head is the list was null, else add to the end */ - if( *head == NULL ) - { - *head = new; - } - else - { - mbedtls_ssl_key_cert *cur = *head; - while( cur->next != NULL ) - cur = cur->next; - cur->next = new; - } - - return( 0 ); -} - -int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ) -{ - return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); -} - -void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ) -{ - conf->ca_chain = ca_chain; - conf->ca_crl = ca_crl; -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ) -{ - return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, - own_cert, pk_key ) ); -} - -void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ) -{ - ssl->handshake->sni_ca_chain = ca_chain; - ssl->handshake->sni_ca_crl = ca_crl; -} - -void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, - int authmode ) -{ - ssl->handshake->sni_authmode = authmode; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -/* - * Set EC J-PAKE password for current handshake - */ -int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, - const unsigned char *pw, - size_t pw_len ) -{ - mbedtls_ecjpake_role role; - - if( ssl->handshake == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - role = MBEDTLS_ECJPAKE_SERVER; - else - role = MBEDTLS_ECJPAKE_CLIENT; - - return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, - role, - MBEDTLS_MD_SHA256, - MBEDTLS_ECP_DP_SECP256R1, - pw, pw_len ) ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, - const unsigned char *psk, size_t psk_len, - const unsigned char *psk_identity, size_t psk_identity_len ) -{ - if( psk == NULL || psk_identity == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( psk_len > MBEDTLS_PSK_MAX_LEN ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* Identity len will be encoded on two bytes */ - if( ( psk_identity_len >> 16 ) != 0 || - psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( conf->psk != NULL || conf->psk_identity != NULL ) - { - mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); - conf->psk = NULL; - conf->psk_identity = NULL; - } - - if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || - ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) - { - mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); - conf->psk = NULL; - conf->psk_identity = NULL; - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - conf->psk_len = psk_len; - conf->psk_identity_len = psk_identity_len; - - memcpy( conf->psk, psk, conf->psk_len ); - memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); - - return( 0 ); -} - -int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, - const unsigned char *psk, size_t psk_len ) -{ - if( psk == NULL || ssl->handshake == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( psk_len > MBEDTLS_PSK_MAX_LEN ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( ssl->handshake->psk != NULL ) - mbedtls_free( ssl->handshake->psk ); - - if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - ssl->handshake->psk_len = psk_len; - memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); - - return( 0 ); -} - -void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_psk ) -{ - conf->f_psk = f_psk; - conf->p_psk = p_psk; -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) -int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) -{ - int ret; - - if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 || - ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 ) - { - mbedtls_mpi_free( &conf->dhm_P ); - mbedtls_mpi_free( &conf->dhm_G ); - return( ret ); - } - - return( 0 ); -} - -int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) -{ - int ret; - - if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || - ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) - { - mbedtls_mpi_free( &conf->dhm_P ); - mbedtls_mpi_free( &conf->dhm_G ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) -/* - * Set the minimum length for Diffie-Hellman parameters - */ -void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, - unsigned int bitlen ) -{ - conf->dhm_min_bitlen = bitlen; -} -#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -/* - * Set allowed/preferred hashes for handshake signatures - */ -void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, - const int *hashes ) -{ - conf->sig_hashes = hashes; -} -#endif - -#if defined(MBEDTLS_ECP_C) -/* - * Set the allowed elliptic curves - */ -void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, - const mbedtls_ecp_group_id *curve_list ) -{ - conf->curve_list = curve_list; -} -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) -{ - size_t hostname_len; - - if( hostname == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - hostname_len = strlen( hostname ); - - if( hostname_len + 1 == 0 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); - - if( ssl->hostname == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( ssl->hostname, hostname, hostname_len ); - - ssl->hostname[hostname_len] = '\0'; - - return( 0 ); -} -#endif - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, - int (*f_sni)(void *, mbedtls_ssl_context *, - const unsigned char *, size_t), - void *p_sni ) -{ - conf->f_sni = f_sni; - conf->p_sni = p_sni; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_SSL_ALPN) -int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) -{ - size_t cur_len, tot_len; - const char **p; - - /* - * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings - * MUST NOT be truncated." - * We check lengths now rather than later. - */ - tot_len = 0; - for( p = protos; *p != NULL; p++ ) - { - cur_len = strlen( *p ); - tot_len += cur_len; - - if( cur_len == 0 || cur_len > 255 || tot_len > 65535 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - conf->alpn_list = protos; - - return( 0 ); -} - -const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) -{ - return( ssl->alpn_chosen ); -} -#endif /* MBEDTLS_SSL_ALPN */ - -void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) -{ - conf->max_major_ver = major; - conf->max_minor_ver = minor; -} - -void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) -{ - conf->min_major_ver = major; - conf->min_minor_ver = minor; -} - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) -void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) -{ - conf->fallback = fallback; -} -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) -{ - conf->encrypt_then_mac = etm; -} -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) -{ - conf->extended_ms = ems; -} -#endif - -#if defined(MBEDTLS_ARC4_C) -void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) -{ - conf->arc4_disabled = arc4; -} -#endif - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) -{ - if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || - mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - conf->mfl_code = mfl_code; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) -{ - conf->trunc_hmac = truncate; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) -{ - conf->cbc_record_splitting = split; -} -#endif - -void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) -{ - conf->allow_legacy_renegotiation = allow_legacy; -} - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) -{ - conf->disable_renegotiation = renegotiation; -} - -void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) -{ - conf->renego_max_records = max_records; -} - -void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, - const unsigned char period[8] ) -{ - memcpy( conf->renego_period, period, 8 ); -} -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -#if defined(MBEDTLS_SSL_CLI_C) -void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) -{ - conf->session_tickets = use_tickets; -} -#endif - -#if defined(MBEDTLS_SSL_SRV_C) -void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, - mbedtls_ssl_ticket_write_t *f_ticket_write, - mbedtls_ssl_ticket_parse_t *f_ticket_parse, - void *p_ticket ) -{ - conf->f_ticket_write = f_ticket_write; - conf->f_ticket_parse = f_ticket_parse; - conf->p_ticket = p_ticket; -} -#endif -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, - mbedtls_ssl_export_keys_t *f_export_keys, - void *p_export_keys ) -{ - conf->f_export_keys = f_export_keys; - conf->p_export_keys = p_export_keys; -} -#endif - -/* - * SSL get accessors - */ -size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) -{ - return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); -} - -uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) -{ - if( ssl->session != NULL ) - return( ssl->session->verify_result ); - - if( ssl->session_negotiate != NULL ) - return( ssl->session_negotiate->verify_result ); - - return( 0xFFFFFFFF ); -} - -const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) -{ - if( ssl == NULL || ssl->session == NULL ) - return( NULL ); - - return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); -} - -const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - switch( ssl->minor_ver ) - { - case MBEDTLS_SSL_MINOR_VERSION_2: - return( "DTLSv1.0" ); - - case MBEDTLS_SSL_MINOR_VERSION_3: - return( "DTLSv1.2" ); - - default: - return( "unknown (DTLS)" ); - } - } -#endif - - switch( ssl->minor_ver ) - { - case MBEDTLS_SSL_MINOR_VERSION_0: - return( "SSLv3.0" ); - - case MBEDTLS_SSL_MINOR_VERSION_1: - return( "TLSv1.0" ); - - case MBEDTLS_SSL_MINOR_VERSION_2: - return( "TLSv1.1" ); - - case MBEDTLS_SSL_MINOR_VERSION_3: - return( "TLSv1.2" ); - - default: - return( "unknown" ); - } -} - -int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) -{ - size_t transform_expansion; - const mbedtls_ssl_transform *transform = ssl->transform_out; - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); -#endif - - if( transform == NULL ) - return( (int) mbedtls_ssl_hdr_len( ssl ) ); - - switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) - { - case MBEDTLS_MODE_GCM: - case MBEDTLS_MODE_CCM: - case MBEDTLS_MODE_STREAM: - transform_expansion = transform->minlen; - break; - - case MBEDTLS_MODE_CBC: - transform_expansion = transform->maclen - + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc ); - break; - - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) ); -} - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) -{ - size_t max_len; - - /* - * Assume mfl_code is correct since it was checked when set - */ - max_len = mfl_code_to_length[ssl->conf->mfl_code]; - - /* - * Check if a smaller max length was negotiated - */ - if( ssl->session_out != NULL && - mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) - { - max_len = mfl_code_to_length[ssl->session_out->mfl_code]; - } - - return max_len; -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) -{ - if( ssl == NULL || ssl->session == NULL ) - return( NULL ); - - return( ssl->session->peer_cert ); -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_CLI_C) -int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst ) -{ - if( ssl == NULL || - dst == NULL || - ssl->session == NULL || - ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - return( ssl_session_copy( dst, ssl->session ) ); -} -#endif /* MBEDTLS_SSL_CLI_C */ - -/* - * Perform a single step of the SSL handshake - */ -int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ret = mbedtls_ssl_handshake_client_step( ssl ); -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ret = mbedtls_ssl_handshake_server_step( ssl ); -#endif - - return( ret ); -} - -/* - * Perform the SSL handshake - */ -int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); - - while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - ret = mbedtls_ssl_handshake_step( ssl ); - - if( ret != 0 ) - break; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); - - return( ret ); -} - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -#if defined(MBEDTLS_SSL_SRV_C) -/* - * Write HelloRequest to request renegotiation on server - */ -static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); - - ssl->out_msglen = 4; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SRV_C */ - -/* - * Actually renegotiate current connection, triggered by either: - * - any side: calling mbedtls_ssl_renegotiate(), - * - client: receiving a HelloRequest during mbedtls_ssl_read(), - * - server: receiving any handshake message on server during mbedtls_ssl_read() after - * the initial handshake is completed. - * If the handshake doesn't complete due to waiting for I/O, it will continue - * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. - */ -static int ssl_start_renegotiation( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); - - if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); - - /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and - * the ServerHello will have message_seq = 1" */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ssl->handshake->out_msg_seq = 1; - else - ssl->handshake->in_msg_seq = 1; - } -#endif - - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; - - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); - - return( 0 ); -} - -/* - * Renegotiate current connection on client, - * or request renegotiation on server - */ -int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_SSL_SRV_C) - /* On server, just send the request */ - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - { - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; - - /* Did we already try/start sending HelloRequest? */ - if( ssl->out_left != 0 ) - return( mbedtls_ssl_flush_output( ssl ) ); - - return( ssl_write_hello_request( ssl ) ); - } -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_CLI_C) - /* - * On client, either start the renegotiation process or, - * if already in progress, continue the handshake - */ - if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); - return( ret ); - } - } - else - { - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_SSL_CLI_C */ - - return( ret ); -} - -/* - * Check record counters and renegotiate if they're above the limit. - */ -static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) -{ - size_t ep_len = ssl_ep_len( ssl ); - int in_ctr_cmp; - int out_ctr_cmp; - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || - ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) - { - return( 0 ); - } - - in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, - ssl->conf->renego_period + ep_len, 8 - ep_len ); - out_ctr_cmp = memcmp( ssl->out_ctr + ep_len, - ssl->conf->renego_period + ep_len, 8 - ep_len ); - - if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) - { - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); - return( mbedtls_ssl_renegotiate( ssl ) ); -} -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/* - * Receive application data decrypted from the SSL layer - */ -int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) -{ - int ret, record_read = 0; - size_t n; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - - if( ssl->handshake != NULL && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - return( ret ); - } - } -#endif - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); - return( ret ); - } -#endif - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - ret = mbedtls_ssl_handshake( ssl ); - if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) - { - record_read = 1; - } - else if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } - - if( ssl->in_offt == NULL ) - { - /* Start timer if not already running */ - if( ssl->f_get_timer != NULL && - ssl->f_get_timer( ssl->p_timer ) == -1 ) - { - ssl_set_timer( ssl, ssl->conf->read_timeout ); - } - - if( ! record_read ) - { - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - } - - if( ssl->in_msglen == 0 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - /* - * OpenSSL sends empty messages to randomize the IV - */ - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); - - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( MBEDTLS_ERR_SSL_WANT_READ ); -#endif - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); - - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( MBEDTLS_ERR_SSL_WANT_READ ); -#endif - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } -#endif - - if( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || - ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == - MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* - * SSLv3 does not have a "no_renegotiation" alert - */ - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) - { - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_WARNING, - MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) - { - return( ret ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else - { - /* DTLS clients need to know renego is server-initiated */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; - } -#endif - ret = ssl_start_renegotiation( ssl ); - if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) - { - record_read = 1; - } - else if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); - return( ret ); - } - } - - /* If a non-handshake record was read during renego, fallthrough, - * else tell the user they should call mbedtls_ssl_read() again */ - if( ! record_read ) - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - - if( ssl->conf->renego_max_records >= 0 ) - { - if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " - "but not honored by client" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - } - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - ssl->in_offt = ssl->in_msg; - - /* We're going to return something now, cancel timer, - * except if handshake (renegotiation) is in progress */ - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - ssl_set_timer( ssl, 0 ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - /* If we requested renego but received AppData, resend HelloRequest. - * Do it now, after setting in_offt, to avoid taking this branch - * again if ssl_write_hello_request() returns WANT_WRITE */ -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ -#endif - } - - n = ( len < ssl->in_msglen ) - ? len : ssl->in_msglen; - - memcpy( buf, ssl->in_offt, n ); - ssl->in_msglen -= n; - - if( ssl->in_msglen == 0 ) - /* all bytes consumed */ - ssl->in_offt = NULL; - else - /* more data available */ - ssl->in_offt += n; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); - - return( (int) n ); -} - -/* - * Send application data to be encrypted by the SSL layer, - * taking care of max fragment length and buffer size - */ -static int ssl_write_real( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - int ret; -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); - - if( len > max_len ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " - "maximum fragment length: %d > %d", - len, max_len ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - else -#endif - len = max_len; - } -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - - if( ssl->out_left != 0 ) - { - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); - return( ret ); - } - } - else - { - - if (len > MBEDTLS_SSL_BUFFER_LEN - 13) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "input larger than the out msg " - "maximum length: 0x%x > 0x%x", - len, MBEDTLS_SSL_BUFFER_LEN - 13 ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - ssl->out_msglen = len; - ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; - memcpy( ssl->out_msg, buf, len ); - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - } - - return( (int) len ); -} - -/* - * Write application data, doing 1/n-1 splitting if necessary. - * - * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, - * then the caller will call us again with the same arguments, so - * remember wether we already did the split or not. - */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -static int ssl_write_split( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - int ret; - - if( ssl->conf->cbc_record_splitting == - MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || - len <= 1 || - ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || - mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) - != MBEDTLS_MODE_CBC ) - { - return( ssl_write_real( ssl, buf, len ) ); - } - - if( ssl->split_done == 0 ) - { - if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) - return( ret ); - ssl->split_done = 1; - } - - if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) - return( ret ); - ssl->split_done = 0; - - return( ret + 1 ); -} -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ - -/* - * Write application data (public-facing wrapper) - */ -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); - return( ret ); - } -#endif - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - ret = ssl_write_split( ssl, buf, len ); -#else - ret = ssl_write_real( ssl, buf, len ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); - - return( ret ); -} - -/* - * Notify the peer that the connection is being closed - */ -int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) -{ - int ret; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); - - if( ssl->out_left != 0 ) - return( mbedtls_ssl_flush_output( ssl ) ); - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_WARNING, - MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); - return( ret ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); - - return( 0 ); -} - -void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) -{ - if( transform == NULL ) - return; - -#if defined(MBEDTLS_ZLIB_SUPPORT) - deflateEnd( &transform->ctx_deflate ); - inflateEnd( &transform->ctx_inflate ); -#endif - - mbedtls_cipher_free( &transform->cipher_ctx_enc ); - mbedtls_cipher_free( &transform->cipher_ctx_dec ); - - mbedtls_md_free( &transform->md_ctx_enc ); - mbedtls_md_free( &transform->md_ctx_dec ); - - mbedtls_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); -} - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) -{ - mbedtls_ssl_key_cert *cur = key_cert, *next; - - while( cur != NULL ) - { - next = cur->next; - mbedtls_free( cur ); - cur = next; - } -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) -{ - if( handshake == NULL ) - return; - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_free( &handshake->fin_md5 ); - mbedtls_sha1_free( &handshake->fin_sha1 ); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_SHA256_ALT) - mbedtls_sha256_free_alt( &handshake->fin_sha256 ); -#else - mbedtls_sha256_free( &handshake->fin_sha256 ); -#endif -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_free( &handshake->fin_sha512 ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_free( &handshake->dhm_ctx ); -#endif -#if defined(MBEDTLS_ECDH_C) - mbedtls_ecdh_free( &handshake->ecdh_ctx ); -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); -#if defined(MBEDTLS_SSL_CLI_C) - mbedtls_free( handshake->ecjpake_cache ); - handshake->ecjpake_cache = NULL; - handshake->ecjpake_cache_len = 0; -#endif -#endif - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - /* explicit void pointer cast for buggy MS compiler */ - mbedtls_free( (void *) handshake->curves ); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( handshake->psk != NULL ) - { - mbedtls_zeroize( handshake->psk, handshake->psk_len ); - mbedtls_free( handshake->psk ); - } -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - /* - * Free only the linked list wrapper, not the keys themselves - * since the belong to the SNI callback - */ - if( handshake->sni_key_cert != NULL ) - { - mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; - - while( cur != NULL ) - { - next = cur->next; - mbedtls_free( cur ); - cur = next; - } - } -#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - mbedtls_free( handshake->verify_cookie ); - mbedtls_free( handshake->hs_msg ); - ssl_flight_free( handshake->flight ); -#endif - - mbedtls_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) ); -} - -void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) -{ - if( session == NULL ) - return; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( session->peer_cert != NULL ) - { - mbedtls_x509_crt_free( session->peer_cert ); - mbedtls_free( session->peer_cert ); - } -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - mbedtls_free( session->ticket ); -#endif - - mbedtls_zeroize( session, sizeof( mbedtls_ssl_session ) ); -} - -/* - * Free an SSL context - */ -void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) -{ - if( ssl == NULL ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); - - if( ssl->out_buf != NULL ) - { - mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); - mbedtls_free( ssl->out_buf ); - } - - if( ssl->in_buf != NULL ) - { - mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); - mbedtls_free( ssl->in_buf ); - } - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->compress_buf != NULL ) - { - mbedtls_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN ); - mbedtls_free( ssl->compress_buf ); - } -#endif - - if( ssl->transform ) - { - mbedtls_ssl_transform_free( ssl->transform ); - mbedtls_free( ssl->transform ); - } - - if( ssl->handshake ) - { - mbedtls_ssl_handshake_free( ssl->handshake ); - mbedtls_ssl_transform_free( ssl->transform_negotiate ); - mbedtls_ssl_session_free( ssl->session_negotiate ); - - mbedtls_free( ssl->handshake ); - mbedtls_free( ssl->transform_negotiate ); - mbedtls_free( ssl->session_negotiate ); - } - - if( ssl->session ) - { - mbedtls_ssl_session_free( ssl->session ); - mbedtls_free( ssl->session ); - } - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( ssl->hostname != NULL ) - { - mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); - mbedtls_free( ssl->hostname ); - } -#endif - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_finish != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); - mbedtls_ssl_hw_record_finish( ssl ); - } -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - mbedtls_free( ssl->cli_id ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); - - /* Actually clear after last debug message */ - mbedtls_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); -} - -/* - * Initialze mbedtls_ssl_config - */ -void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) -{ - memset( conf, 0, sizeof( mbedtls_ssl_config ) ); -} - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -static int ssl_preset_default_hashes[] = { -#if defined(MBEDTLS_SHA512_C) - MBEDTLS_MD_SHA512, - MBEDTLS_MD_SHA384, -#endif -#if defined(MBEDTLS_SHA256_C) - MBEDTLS_MD_SHA256, -#endif -#if defined(MBEDTLS_SHA1_C) - MBEDTLS_MD_SHA1, -#endif -#if defined(MBEDTLS_MD5_C) - MBEDTLS_MD_MD5, -#endif - MBEDTLS_MD_NONE -}; -#endif - -#if !defined(MBEDTLS_IOT_SPECIFIC) -static int ssl_preset_suiteb_ciphersuites[] = { - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - 0 -}; - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -static int ssl_preset_suiteb_hashes[] = { - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA384, - MBEDTLS_MD_NONE -}; -#endif - -#if defined(MBEDTLS_ECP_C) -static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { - MBEDTLS_ECP_DP_SECP256R1, - MBEDTLS_ECP_DP_SECP384R1, - MBEDTLS_ECP_DP_NONE -}; -#endif -#endif /* MBEDTLS_IOT_SPECIFIC */ - -/* - * Load default in mbedtls_ssl_config - */ -int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, - int endpoint, int transport, int preset ) -{ -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) - int ret; -#endif - - /* Use the functions here so that they are covered in tests, - * but otherwise access member directly for efficiency */ - mbedtls_ssl_conf_endpoint( conf, endpoint ); - mbedtls_ssl_conf_transport( conf, transport ); - - /* - * Things that are common to all presets - */ -#if defined(MBEDTLS_SSL_CLI_C) - if( endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; -#endif - } -#endif - -#if defined(MBEDTLS_ARC4_C) - conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - conf->f_cookie_write = ssl_cookie_write_dummy; - conf->f_cookie_check = ssl_cookie_check_dummy; -#endif - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; - conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; -#endif - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; - memset( conf->renego_period, 0x00, 2 ); - memset( conf->renego_period + 2, 0xFF, 6 ); -#endif - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) - if( endpoint == MBEDTLS_SSL_IS_SERVER ) - { - if( ( ret = mbedtls_ssl_conf_dh_param( conf, - MBEDTLS_DHM_RFC5114_MODP_2048_P, - MBEDTLS_DHM_RFC5114_MODP_2048_G ) ) != 0 ) - { - return( ret ); - } - } -#endif - - /* - * Preset-specific defaults - */ - switch( preset ) - { -#if !defined(MBEDTLS_IOT_SPECIFIC) - /* - * NSA Suite B - */ - case MBEDTLS_SSL_PRESET_SUITEB: - conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ - conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; - conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; - - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = - ssl_preset_suiteb_ciphersuites; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - conf->sig_hashes = ssl_preset_suiteb_hashes; -#endif - -#if defined(MBEDTLS_ECP_C) - conf->curve_list = ssl_preset_suiteb_curves; -#endif - break; -#endif /* MBEDTLS_IOT_SPECIFIC */ - - /* - * Default - */ - default: - conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ - conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; - conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; -#endif - - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = - mbedtls_ssl_list_ciphersuites(); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - conf->cert_profile = &mbedtls_x509_crt_profile_default; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - conf->sig_hashes = ssl_preset_default_hashes; -#endif - -#if defined(MBEDTLS_ECP_C) - conf->curve_list = mbedtls_ecp_grp_id_list(); -#endif - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) - conf->dhm_min_bitlen = 1024; -#endif - } - - return( 0 ); -} - -/* - * Free mbedtls_ssl_config - */ -void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) -{ -#if defined(MBEDTLS_DHM_C) - mbedtls_mpi_free( &conf->dhm_P ); - mbedtls_mpi_free( &conf->dhm_G ); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( conf->psk != NULL ) - { - mbedtls_zeroize( conf->psk, conf->psk_len ); - mbedtls_zeroize( conf->psk_identity, conf->psk_identity_len ); - mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); - conf->psk_len = 0; - conf->psk_identity_len = 0; - } -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - ssl_key_cert_free( conf->key_cert ); -#endif - - mbedtls_zeroize( conf, sizeof( mbedtls_ssl_config ) ); -} - -#if defined(MBEDTLS_PK_C) && \ - ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) -/* - * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX - */ -unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) -{ -#if defined(MBEDTLS_RSA_C) - if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) - return( MBEDTLS_SSL_SIG_RSA ); -#endif -#if defined(MBEDTLS_ECDSA_C) - if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) - return( MBEDTLS_SSL_SIG_ECDSA ); -#endif - return( MBEDTLS_SSL_SIG_ANON ); -} - -mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) -{ - switch( sig ) - { -#if defined(MBEDTLS_RSA_C) - case MBEDTLS_SSL_SIG_RSA: - return( MBEDTLS_PK_RSA ); -#endif -#if defined(MBEDTLS_ECDSA_C) - case MBEDTLS_SSL_SIG_ECDSA: - return( MBEDTLS_PK_ECDSA ); -#endif - default: - return( MBEDTLS_PK_NONE ); - } -} -#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ - -/* - * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX - */ -mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) -{ - switch( hash ) - { -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_SSL_HASH_MD5: - return( MBEDTLS_MD_MD5 ); -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_SSL_HASH_SHA1: - return( MBEDTLS_MD_SHA1 ); -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_SSL_HASH_SHA224: - return( MBEDTLS_MD_SHA224 ); - case MBEDTLS_SSL_HASH_SHA256: - return( MBEDTLS_MD_SHA256 ); -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_SSL_HASH_SHA384: - return( MBEDTLS_MD_SHA384 ); - case MBEDTLS_SSL_HASH_SHA512: - return( MBEDTLS_MD_SHA512 ); -#endif - default: - return( MBEDTLS_MD_NONE ); - } -} - -/* - * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX - */ -unsigned char mbedtls_ssl_hash_from_md_alg( int md ) -{ - switch( md ) - { -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_MD_MD5: - return( MBEDTLS_SSL_HASH_MD5 ); -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_MD_SHA1: - return( MBEDTLS_SSL_HASH_SHA1 ); -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_SHA224: - return( MBEDTLS_SSL_HASH_SHA224 ); - case MBEDTLS_MD_SHA256: - return( MBEDTLS_SSL_HASH_SHA256 ); -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_MD_SHA384: - return( MBEDTLS_SSL_HASH_SHA384 ); - case MBEDTLS_MD_SHA512: - return( MBEDTLS_SSL_HASH_SHA512 ); -#endif - default: - return( MBEDTLS_SSL_HASH_NONE ); - } -} - -#if defined(MBEDTLS_ECP_C) -/* - * Check if a curve proposed by the peer is in our list. - * Return 0 if we're willing to use it, -1 otherwise. - */ -int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) -{ - const mbedtls_ecp_group_id *gid; - - if( ssl->conf->curve_list == NULL ) - return( -1 ); - - for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) - if( *gid == grp_id ) - return( 0 ); - - return( -1 ); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -/* - * Check if a hash proposed by the peer is in our list. - * Return 0 if we're willing to use it, -1 otherwise. - */ -int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, - mbedtls_md_type_t md ) -{ - const int *cur; - - if( ssl->conf->sig_hashes == NULL ) - return( -1 ); - - for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) - if( *cur == (int) md ) - return( 0 ); - - return( -1 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, - const mbedtls_ssl_ciphersuite_t *ciphersuite, - int cert_endpoint, - uint32_t *flags ) -{ - int ret = 0; -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - int usage = 0; -#endif -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - const char *ext_oid; - size_t ext_len; -#endif - -#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ - !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - ((void) cert); - ((void) cert_endpoint); - ((void) flags); -#endif - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) - { - /* Server part of the key exchange */ - switch( ciphersuite->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; - break; - - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; - break; - - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - usage = MBEDTLS_X509_KU_KEY_AGREEMENT; - break; - - /* Don't use default: we want warnings when adding new values */ - case MBEDTLS_KEY_EXCHANGE_NONE: - case MBEDTLS_KEY_EXCHANGE_PSK: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECJPAKE: - usage = 0; - } - } - else - { - /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ - usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; - } - - if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) - { - *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; - ret = -1; - } -#else - ((void) ciphersuite); -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ - -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) - { - ext_oid = MBEDTLS_OID_SERVER_AUTH; - ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); - } - else - { - ext_oid = MBEDTLS_OID_CLIENT_AUTH; - ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); - } - - if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) - { - *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; - ret = -1; - } -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ - - return( ret ); -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/* - * Convert version numbers to/from wire format - * and, for DTLS, to/from TLS equivalent. - * - * For TLS this is the identity. - * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: - * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) - * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) - */ -void mbedtls_ssl_write_version( int major, int minor, int transport, - unsigned char ver[2] ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) - --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ - - ver[0] = (unsigned char)( 255 - ( major - 2 ) ); - ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); - } - else -#else - ((void) transport); -#endif - { - ver[0] = (unsigned char) major; - ver[1] = (unsigned char) minor; - } -} - -void mbedtls_ssl_read_version( int *major, int *minor, int transport, - const unsigned char ver[2] ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - *major = 255 - ver[0] + 2; - *minor = 255 - ver[1] + 1; - - if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) - ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ - } - else -#else - ((void) transport); -#endif - { - *major = ver[0]; - *minor = ver[1]; - } -} - -int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) -{ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; - - switch( md ) - { -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_SSL_HASH_MD5: - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_SSL_HASH_SHA1: - ssl->handshake->calc_verify = ssl_calc_verify_tls; - break; -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_SSL_HASH_SHA384: - ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; - break; -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_SSL_HASH_SHA256: - ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; - break; -#endif - default: - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; - } - - return 0; -#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ - (void) ssl; - (void) md; - - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -} - -#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/components/security/mbedtls/src/threading.c b/components/security/mbedtls/src/threading.c deleted file mode 100644 index 81c10754..00000000 --- a/components/security/mbedtls/src/threading.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Threading abstraction layer - * - * 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_THREADING_C) - -#include "mbedtls/threading.h" - -#if defined(MBEDTLS_THREADING_PTHREAD) -static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL || mutex->is_valid ) - return; - - mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; -} - -static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL || !mutex->is_valid ) - return; - - (void) pthread_mutex_destroy( &mutex->mutex ); - mutex->is_valid = 0; -} - -static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL || ! mutex->is_valid ) - return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); - - if( pthread_mutex_lock( &mutex->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - - return( 0 ); -} - -static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL || ! mutex->is_valid ) - return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); - - if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - - return( 0 ); -} - -void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; -void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; -int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; -int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; - -/* - * With phtreads we can statically initialize mutexes - */ -#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } - -#endif /* MBEDTLS_THREADING_PTHREAD */ - -#if defined(MBEDTLS_THREADING_ALT) -static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) -{ - ((void) mutex ); - return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); -} -static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) -{ - ((void) mutex ); - return; -} - -void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; -void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; -int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; -int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; - -/* - * Set functions pointers and initialize global mutexes - */ -void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), - void (*mutex_free)( mbedtls_threading_mutex_t * ), - int (*mutex_lock)( mbedtls_threading_mutex_t * ), - int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) -{ - mbedtls_mutex_init = mutex_init; - mbedtls_mutex_free = mutex_free; - mbedtls_mutex_lock = mutex_lock; - mbedtls_mutex_unlock = mutex_unlock; - - mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); - mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - mbedtls_mutex_init( &mbedtls_threading_ecp_mutex ); -#endif -} - -/* - * Free global mutexes - */ -void mbedtls_threading_free_alt( void ) -{ - mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); - mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - mbedtls_mutex_free( &mbedtls_threading_ecp_mutex ); -#endif -} -#endif /* MBEDTLS_THREADING_ALT */ - -/* - * Define global mutexes - */ -#ifndef MUTEX_INIT -#define MUTEX_INIT -#endif -mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; -mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; -#if defined(MBEDTLS_ECP_INTERNAL_ALT) -mbedtls_threading_mutex_t mbedtls_threading_ecp_mutex MUTEX_INIT; -#endif - -#endif /* MBEDTLS_THREADING_C */ diff --git a/components/security/mbedtls/src/timing.c b/components/security/mbedtls/src/timing.c deleted file mode 100644 index eaf75b35..00000000 --- a/components/security/mbedtls/src/timing.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Portable interface to the CPU cycle counter - * - * 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_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif - -#if defined(MBEDTLS_TIMING_C) - -#include "mbedtls/timing.h" - -#if !defined(MBEDTLS_TIMING_ALT) - -#ifndef asm -#define asm __asm -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - -#include -#include - -struct _hr_time -{ - LARGE_INTEGER start; -}; - -#else - -#include -#include -#include -#include -#include - -struct _hr_time -{ - struct timeval start; -}; - -#endif /* _WIN32 && !EFIX64 && !EFI32 */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long tsc; - __asm rdtsc - __asm mov [tsc], eax - return( tsc ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ - -/* some versions of mingw-64 have 32-bit longs even on x84_64 */ -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && ( defined(__i386__) || ( \ - ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long lo, hi; - asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); - return( lo ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __i386__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long lo, hi; - asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); - return( lo | ( hi << 32 ) ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && ( __amd64__ || __x86_64__ ) */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long tbl, tbu0, tbu1; - - do - { - asm volatile( "mftbu %0" : "=r" (tbu0) ); - asm volatile( "mftb %0" : "=r" (tbl ) ); - asm volatile( "mftbu %0" : "=r" (tbu1) ); - } - while( tbu0 != tbu1 ); - - return( tbl ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && ( __powerpc__ || __ppc__ ) */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__sparc64__) - -#if defined(__OpenBSD__) -#warning OpenBSD does not allow access to tick register using software version instead -#else -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long tick; - asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); - return( tick ); -} -#endif /* __OpenBSD__ */ -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __sparc64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long tick; - asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); - asm volatile( "mov %%g1, %0" : "=r" (tick) ); - return( tick ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __sparc__ && !__sparc64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__alpha__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long cc; - asm volatile( "rpcc %0" : "=r" (cc) ); - return( cc & 0xFFFFFFFF ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __alpha__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__ia64__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long itc; - asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); - return( itc ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __ia64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ - !defined(EFIX64) && !defined(EFI32) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - LARGE_INTEGER offset; - - QueryPerformanceCounter( &offset ); - - return( (unsigned long)( offset.QuadPart ) ); -} -#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ - -#if !defined(HAVE_HARDCLOCK) - -#define HAVE_HARDCLOCK - -static int hardclock_init = 0; -static struct timeval tv_init; - -unsigned long mbedtls_timing_hardclock( void ) -{ - struct timeval tv_cur; - - if( hardclock_init == 0 ) - { - gettimeofday( &tv_init, NULL ); - hardclock_init = 1; - } - - gettimeofday( &tv_cur, NULL ); - return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 - + ( tv_cur.tv_usec - tv_init.tv_usec ) ); -} -#endif /* !HAVE_HARDCLOCK */ - -volatile int mbedtls_timing_alarmed = 0; - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - -unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) -{ - unsigned long delta; - LARGE_INTEGER offset, hfreq; - struct _hr_time *t = (struct _hr_time *) val; - - QueryPerformanceCounter( &offset ); - QueryPerformanceFrequency( &hfreq ); - - delta = (unsigned long)( ( 1000 * - ( offset.QuadPart - t->start.QuadPart ) ) / - hfreq.QuadPart ); - - if( reset ) - QueryPerformanceCounter( &t->start ); - - return( delta ); -} - -/* It's OK to use a global because alarm() is supposed to be global anyway */ -static DWORD alarmMs; - -static DWORD WINAPI TimerProc( LPVOID TimerContext ) -{ - ((void) TimerContext); - Sleep( alarmMs ); - mbedtls_timing_alarmed = 1; - return( TRUE ); -} - -void mbedtls_set_alarm( int seconds ) -{ - DWORD ThreadId; - - mbedtls_timing_alarmed = 0; - alarmMs = seconds * 1000; - CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); -} - -#else /* _WIN32 && !EFIX64 && !EFI32 */ - -unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) -{ - unsigned long delta; - struct timeval offset; - struct _hr_time *t = (struct _hr_time *) val; - - gettimeofday( &offset, NULL ); - - if( reset ) - { - t->start.tv_sec = offset.tv_sec; - t->start.tv_usec = offset.tv_usec; - return( 0 ); - } - - delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 - + ( offset.tv_usec - t->start.tv_usec ) / 1000; - - return( delta ); -} - -#ifndef CONFIG_PLAT_AOS -static void sighandler( int signum ) -{ - mbedtls_timing_alarmed = 1; - signal( signum, sighandler ); -} - -void mbedtls_set_alarm( int seconds ) -{ - mbedtls_timing_alarmed = 0; - signal( SIGALRM, sighandler ); - alarm( seconds ); -} -#endif - -#endif /* _WIN32 && !EFIX64 && !EFI32 */ - -/* - * Set delays to watch - */ -void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) -{ - mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; - - ctx->int_ms = int_ms; - ctx->fin_ms = fin_ms; - - if( fin_ms != 0 ) - (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); -} - -/* - * Get number of delays expired - */ -int mbedtls_timing_get_delay( void *data ) -{ - mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; - unsigned long elapsed_ms; - - if( ctx->fin_ms == 0 ) - return( -1 ); - - elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); - - if( elapsed_ms >= ctx->fin_ms ) - return( 2 ); - - if( elapsed_ms >= ctx->int_ms ) - return( 1 ); - - return( 0 ); -} - -#endif /* !MBEDTLS_TIMING_ALT */ - -#if defined(MBEDTLS_SELF_TEST) - -/* - * Busy-waits for the given number of milliseconds. - * Used for testing mbedtls_timing_hardclock. - */ -static void busy_msleep( unsigned long msec ) -{ - struct mbedtls_timing_hr_time hires; - unsigned long i = 0; /* for busy-waiting */ - volatile unsigned long j; /* to prevent optimisation */ - - (void) mbedtls_timing_get_timer( &hires, 1 ); - - while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) - i++; - - j = i; - (void) j; -} - -#define FAIL do \ -{ \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - \ - return( 1 ); \ -} while( 0 ) - -/* - * Checkup routine - * - * Warning: this is work in progress, some tests may not be reliable enough - * yet! False positives may happen. - */ -int mbedtls_timing_self_test( int verbose ) -{ - unsigned long cycles, ratio; - unsigned long millisecs, secs; - int hardfail; - struct mbedtls_timing_hr_time hires; - uint32_t a, b; - mbedtls_timing_delay_context ctx; - - if( verbose != 0 ) - mbedtls_printf( " TIMING tests note: will take some time!\n" ); - - - if( verbose != 0 ) - mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); - - for( secs = 1; secs <= 3; secs++ ) - { - (void) mbedtls_timing_get_timer( &hires, 1 ); - - mbedtls_set_alarm( (int) secs ); - while( !mbedtls_timing_alarmed ) - ; - - millisecs = mbedtls_timing_get_timer( &hires, 0 ); - - /* For some reason on Windows it looks like alarm has an extra delay - * (maybe related to creating a new thread). Allow some room here. */ - if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); - - for( a = 200; a <= 400; a += 200 ) - { - for( b = 200; b <= 400; b += 200 ) - { - mbedtls_timing_set_delay( &ctx, a, a + b ); - - busy_msleep( a - a / 8 ); - if( mbedtls_timing_get_delay( &ctx ) != 0 ) - FAIL; - - busy_msleep( a / 4 ); - if( mbedtls_timing_get_delay( &ctx ) != 1 ) - FAIL; - - busy_msleep( b - a / 8 - b / 8 ); - if( mbedtls_timing_get_delay( &ctx ) != 1 ) - FAIL; - - busy_msleep( b / 4 ); - if( mbedtls_timing_get_delay( &ctx ) != 2 ) - FAIL; - } - } - - mbedtls_timing_set_delay( &ctx, 0, 0 ); - busy_msleep( 200 ); - if( mbedtls_timing_get_delay( &ctx ) != -1 ) - FAIL; - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); - - /* - * Allow one failure for possible counter wrapping. - * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; - * since the whole test is about 10ms, it shouldn't happen twice in a row. - */ - hardfail = 0; - -hard_test: - if( hardfail > 1 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed (ignored)\n" ); - - goto hard_test_done; - } - - /* Get a reference ratio cycles/ms */ - millisecs = 1; - cycles = mbedtls_timing_hardclock(); - busy_msleep( millisecs ); - cycles = mbedtls_timing_hardclock() - cycles; - ratio = cycles / millisecs; - - /* Check that the ratio is mostly constant */ - for( millisecs = 2; millisecs <= 4; millisecs++ ) - { - cycles = mbedtls_timing_hardclock(); - busy_msleep( millisecs ); - cycles = mbedtls_timing_hardclock() - cycles; - - /* Allow variation up to 20% */ - if( cycles / millisecs < ratio - ratio / 5 || - cycles / millisecs > ratio + ratio / 5 ) - { - hardfail++; - goto hard_test; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -hard_test_done: - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_TIMING_C */ diff --git a/components/security/mbedtls/src/version.c b/components/security/mbedtls/src/version.c deleted file mode 100644 index 6ca80d46..00000000 --- a/components/security/mbedtls/src/version.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Version information - * - * 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_VERSION_C) - -#include "mbedtls/version.h" -#include - -unsigned int mbedtls_version_get_number() -{ - return( MBEDTLS_VERSION_NUMBER ); -} - -void mbedtls_version_get_string( char *string ) -{ - memcpy( string, MBEDTLS_VERSION_STRING, - sizeof( MBEDTLS_VERSION_STRING ) ); -} - -void mbedtls_version_get_string_full( char *string ) -{ - memcpy( string, MBEDTLS_VERSION_STRING_FULL, - sizeof( MBEDTLS_VERSION_STRING_FULL ) ); -} - -#endif /* MBEDTLS_VERSION_C */ diff --git a/components/security/mbedtls/src/version_features.c b/components/security/mbedtls/src/version_features.c deleted file mode 100644 index 9f97c7bc..00000000 --- a/components/security/mbedtls/src/version_features.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Version feature information - * - * 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_VERSION_C) - -#include "mbedtls/version.h" - -#include - -static const char *features[] = { -#if defined(MBEDTLS_VERSION_FEATURES) -#if defined(MBEDTLS_HAVE_ASM) - "MBEDTLS_HAVE_ASM", -#endif /* MBEDTLS_HAVE_ASM */ -#if defined(MBEDTLS_HAVE_SSE2) - "MBEDTLS_HAVE_SSE2", -#endif /* MBEDTLS_HAVE_SSE2 */ -#if defined(MBEDTLS_HAVE_TIME) - "MBEDTLS_HAVE_TIME", -#endif /* MBEDTLS_HAVE_TIME */ -#if defined(MBEDTLS_HAVE_TIME_DATE) - "MBEDTLS_HAVE_TIME_DATE", -#endif /* MBEDTLS_HAVE_TIME_DATE */ -#if defined(MBEDTLS_PLATFORM_MEMORY) - "MBEDTLS_PLATFORM_MEMORY", -#endif /* MBEDTLS_PLATFORM_MEMORY */ -#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) - "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", -#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) - "MBEDTLS_PLATFORM_EXIT_ALT", -#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ -#if defined(MBEDTLS_PLATFORM_TIME_ALT) - "MBEDTLS_PLATFORM_TIME_ALT", -#endif /* MBEDTLS_PLATFORM_TIME_ALT */ -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) - "MBEDTLS_PLATFORM_FPRINTF_ALT", -#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) - "MBEDTLS_PLATFORM_PRINTF_ALT", -#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) - "MBEDTLS_PLATFORM_SNPRINTF_ALT", -#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) - "MBEDTLS_PLATFORM_NV_SEED_ALT", -#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ -#if defined(MBEDTLS_DEPRECATED_WARNING) - "MBEDTLS_DEPRECATED_WARNING", -#endif /* MBEDTLS_DEPRECATED_WARNING */ -#if defined(MBEDTLS_DEPRECATED_REMOVED) - "MBEDTLS_DEPRECATED_REMOVED", -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#if defined(MBEDTLS_TIMING_ALT) - "MBEDTLS_TIMING_ALT", -#endif /* MBEDTLS_TIMING_ALT */ -#if defined(MBEDTLS_AES_ALT) - "MBEDTLS_AES_ALT", -#endif /* MBEDTLS_AES_ALT */ -#if defined(MBEDTLS_ARC4_ALT) - "MBEDTLS_ARC4_ALT", -#endif /* MBEDTLS_ARC4_ALT */ -#if defined(MBEDTLS_BLOWFISH_ALT) - "MBEDTLS_BLOWFISH_ALT", -#endif /* MBEDTLS_BLOWFISH_ALT */ -#if defined(MBEDTLS_CAMELLIA_ALT) - "MBEDTLS_CAMELLIA_ALT", -#endif /* MBEDTLS_CAMELLIA_ALT */ -#if defined(MBEDTLS_DES_ALT) - "MBEDTLS_DES_ALT", -#endif /* MBEDTLS_DES_ALT */ -#if defined(MBEDTLS_XTEA_ALT) - "MBEDTLS_XTEA_ALT", -#endif /* MBEDTLS_XTEA_ALT */ -#if defined(MBEDTLS_MD2_ALT) - "MBEDTLS_MD2_ALT", -#endif /* MBEDTLS_MD2_ALT */ -#if defined(MBEDTLS_MD4_ALT) - "MBEDTLS_MD4_ALT", -#endif /* MBEDTLS_MD4_ALT */ -#if defined(MBEDTLS_MD5_ALT) - "MBEDTLS_MD5_ALT", -#endif /* MBEDTLS_MD5_ALT */ -#if defined(MBEDTLS_RIPEMD160_ALT) - "MBEDTLS_RIPEMD160_ALT", -#endif /* MBEDTLS_RIPEMD160_ALT */ -#if defined(MBEDTLS_SHA1_ALT) - "MBEDTLS_SHA1_ALT", -#endif /* MBEDTLS_SHA1_ALT */ -#if defined(MBEDTLS_SHA256_ALT) - "MBEDTLS_SHA256_ALT", -#endif /* MBEDTLS_SHA256_ALT */ -#if defined(MBEDTLS_SHA512_ALT) - "MBEDTLS_SHA512_ALT", -#endif /* MBEDTLS_SHA512_ALT */ -#if defined(MBEDTLS_ECP_ALT) - "MBEDTLS_ECP_ALT", -#endif /* MBEDTLS_ECP_ALT */ -#if defined(MBEDTLS_MD2_PROCESS_ALT) - "MBEDTLS_MD2_PROCESS_ALT", -#endif /* MBEDTLS_MD2_PROCESS_ALT */ -#if defined(MBEDTLS_MD4_PROCESS_ALT) - "MBEDTLS_MD4_PROCESS_ALT", -#endif /* MBEDTLS_MD4_PROCESS_ALT */ -#if defined(MBEDTLS_MD5_PROCESS_ALT) - "MBEDTLS_MD5_PROCESS_ALT", -#endif /* MBEDTLS_MD5_PROCESS_ALT */ -#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) - "MBEDTLS_RIPEMD160_PROCESS_ALT", -#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ -#if defined(MBEDTLS_SHA1_PROCESS_ALT) - "MBEDTLS_SHA1_PROCESS_ALT", -#endif /* MBEDTLS_SHA1_PROCESS_ALT */ -#if defined(MBEDTLS_SHA256_PROCESS_ALT) - "MBEDTLS_SHA256_PROCESS_ALT", -#endif /* MBEDTLS_SHA256_PROCESS_ALT */ -#if defined(MBEDTLS_SHA512_PROCESS_ALT) - "MBEDTLS_SHA512_PROCESS_ALT", -#endif /* MBEDTLS_SHA512_PROCESS_ALT */ -#if defined(MBEDTLS_DES_SETKEY_ALT) - "MBEDTLS_DES_SETKEY_ALT", -#endif /* MBEDTLS_DES_SETKEY_ALT */ -#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) - "MBEDTLS_DES_CRYPT_ECB_ALT", -#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ -#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) - "MBEDTLS_DES3_CRYPT_ECB_ALT", -#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ -#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) - "MBEDTLS_AES_SETKEY_ENC_ALT", -#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ -#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) - "MBEDTLS_AES_SETKEY_DEC_ALT", -#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ -#if defined(MBEDTLS_AES_ENCRYPT_ALT) - "MBEDTLS_AES_ENCRYPT_ALT", -#endif /* MBEDTLS_AES_ENCRYPT_ALT */ -#if defined(MBEDTLS_AES_DECRYPT_ALT) - "MBEDTLS_AES_DECRYPT_ALT", -#endif /* MBEDTLS_AES_DECRYPT_ALT */ -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - "MBEDTLS_ECP_INTERNAL_ALT", -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) - "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", -#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) - "MBEDTLS_ECP_ADD_MIXED_ALT", -#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) - "MBEDTLS_ECP_DOUBLE_JAC_ALT", -#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) - "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", -#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) - "MBEDTLS_ECP_NORMALIZE_JAC_ALT", -#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) - "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", -#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) - "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", -#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) - "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", -#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ -#if defined(MBEDTLS_TEST_NULL_ENTROPY) - "MBEDTLS_TEST_NULL_ENTROPY", -#endif /* MBEDTLS_TEST_NULL_ENTROPY */ -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - "MBEDTLS_ENTROPY_HARDWARE_ALT", -#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ -#if defined(MBEDTLS_AES_ROM_TABLES) - "MBEDTLS_AES_ROM_TABLES", -#endif /* MBEDTLS_AES_ROM_TABLES */ -#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) - "MBEDTLS_CAMELLIA_SMALL_MEMORY", -#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) - "MBEDTLS_CIPHER_MODE_CBC", -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CIPHER_MODE_CFB) - "MBEDTLS_CIPHER_MODE_CFB", -#endif /* MBEDTLS_CIPHER_MODE_CFB */ -#if defined(MBEDTLS_CIPHER_MODE_CTR) - "MBEDTLS_CIPHER_MODE_CTR", -#endif /* MBEDTLS_CIPHER_MODE_CTR */ -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) - "MBEDTLS_CIPHER_NULL_CIPHER", -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) - "MBEDTLS_CIPHER_PADDING_PKCS7", -#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ -#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) - "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", -#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) - "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", -#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) - "MBEDTLS_CIPHER_PADDING_ZEROS", -#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ -#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) - "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", -#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ -#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) - "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", -#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - "MBEDTLS_ECP_DP_SECP192R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - "MBEDTLS_ECP_DP_SECP224R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - "MBEDTLS_ECP_DP_SECP256R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - "MBEDTLS_ECP_DP_SECP384R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - "MBEDTLS_ECP_DP_SECP521R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - "MBEDTLS_ECP_DP_SECP192K1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - "MBEDTLS_ECP_DP_SECP224K1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - "MBEDTLS_ECP_DP_SECP256K1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - "MBEDTLS_ECP_DP_BP256R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - "MBEDTLS_ECP_DP_BP384R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - "MBEDTLS_ECP_DP_BP512R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - "MBEDTLS_ECP_DP_CURVE25519_ENABLED", -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ -#if defined(MBEDTLS_ECP_NIST_OPTIM) - "MBEDTLS_ECP_NIST_OPTIM", -#endif /* MBEDTLS_ECP_NIST_OPTIM */ -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) - "MBEDTLS_ECDSA_DETERMINISTIC", -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - "MBEDTLS_PK_PARSE_EC_EXTENDED", -#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ -#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) - "MBEDTLS_ERROR_STRERROR_DUMMY", -#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ -#if defined(MBEDTLS_GENPRIME) - "MBEDTLS_GENPRIME", -#endif /* MBEDTLS_GENPRIME */ -#if defined(MBEDTLS_FS_IO) - "MBEDTLS_FS_IO", -#endif /* MBEDTLS_FS_IO */ -#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) - "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", -#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ -#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) - "MBEDTLS_NO_PLATFORM_ENTROPY", -#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ -#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) - "MBEDTLS_ENTROPY_FORCE_SHA256", -#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ -#if defined(MBEDTLS_ENTROPY_NV_SEED) - "MBEDTLS_ENTROPY_NV_SEED", -#endif /* MBEDTLS_ENTROPY_NV_SEED */ -#if defined(MBEDTLS_MEMORY_DEBUG) - "MBEDTLS_MEMORY_DEBUG", -#endif /* MBEDTLS_MEMORY_DEBUG */ -#if defined(MBEDTLS_MEMORY_BACKTRACE) - "MBEDTLS_MEMORY_BACKTRACE", -#endif /* MBEDTLS_MEMORY_BACKTRACE */ -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) - "MBEDTLS_PK_RSA_ALT_SUPPORT", -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ -#if defined(MBEDTLS_PKCS1_V15) - "MBEDTLS_PKCS1_V15", -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) - "MBEDTLS_PKCS1_V21", -#endif /* MBEDTLS_PKCS1_V21 */ -#if defined(MBEDTLS_RSA_NO_CRT) - "MBEDTLS_RSA_NO_CRT", -#endif /* MBEDTLS_RSA_NO_CRT */ -#if defined(MBEDTLS_SELF_TEST) - "MBEDTLS_SELF_TEST", -#endif /* MBEDTLS_SELF_TEST */ -#if defined(MBEDTLS_SHA256_SMALLER) - "MBEDTLS_SHA256_SMALLER", -#endif /* MBEDTLS_SHA256_SMALLER */ -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - "MBEDTLS_SSL_ALL_ALERT_MESSAGES", -#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ -#if defined(MBEDTLS_SSL_DEBUG_ALL) - "MBEDTLS_SSL_DEBUG_ALL", -#endif /* MBEDTLS_SSL_DEBUG_ALL */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - "MBEDTLS_SSL_ENCRYPT_THEN_MAC", -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - "MBEDTLS_SSL_FALLBACK_SCSV", -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - "MBEDTLS_SSL_HW_RECORD_ACCEL", -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - "MBEDTLS_SSL_CBC_RECORD_SPLITTING", -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - "MBEDTLS_SSL_RENEGOTIATION", -#endif /* MBEDTLS_SSL_RENEGOTIATION */ -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) - "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", -#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", -#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - "MBEDTLS_SSL_PROTO_SSL3", -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) - "MBEDTLS_SSL_PROTO_TLS1", -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) - "MBEDTLS_SSL_PROTO_TLS1_1", -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - "MBEDTLS_SSL_PROTO_TLS1_2", -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - "MBEDTLS_SSL_PROTO_DTLS", -#endif /* MBEDTLS_SSL_PROTO_DTLS */ -#if defined(MBEDTLS_SSL_ALPN) - "MBEDTLS_SSL_ALPN", -#endif /* MBEDTLS_SSL_ALPN */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - "MBEDTLS_SSL_DTLS_ANTI_REPLAY", -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) - "MBEDTLS_SSL_DTLS_HELLO_VERIFY", -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) - "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - "MBEDTLS_SSL_SESSION_TICKETS", -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - "MBEDTLS_SSL_EXPORT_KEYS", -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - "MBEDTLS_SSL_SERVER_NAME_INDICATION", -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - "MBEDTLS_SSL_TRUNCATED_HMAC", -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ -#if defined(MBEDTLS_THREADING_ALT) - "MBEDTLS_THREADING_ALT", -#endif /* MBEDTLS_THREADING_ALT */ -#if defined(MBEDTLS_THREADING_PTHREAD) - "MBEDTLS_THREADING_PTHREAD", -#endif /* MBEDTLS_THREADING_PTHREAD */ -#if defined(MBEDTLS_VERSION_FEATURES) - "MBEDTLS_VERSION_FEATURES", -#endif /* MBEDTLS_VERSION_FEATURES */ -#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) - "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", -#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ -#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", -#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - "MBEDTLS_X509_CHECK_KEY_USAGE", -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - "MBEDTLS_X509_RSASSA_PSS_SUPPORT", -#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - "MBEDTLS_ZLIB_SUPPORT", -#endif /* MBEDTLS_ZLIB_SUPPORT */ -#if defined(MBEDTLS_AESNI_C) - "MBEDTLS_AESNI_C", -#endif /* MBEDTLS_AESNI_C */ -#if defined(MBEDTLS_AES_C) - "MBEDTLS_AES_C", -#endif /* MBEDTLS_AES_C */ -#if defined(MBEDTLS_ARC4_C) - "MBEDTLS_ARC4_C", -#endif /* MBEDTLS_ARC4_C */ -#if defined(MBEDTLS_ASN1_PARSE_C) - "MBEDTLS_ASN1_PARSE_C", -#endif /* MBEDTLS_ASN1_PARSE_C */ -#if defined(MBEDTLS_ASN1_WRITE_C) - "MBEDTLS_ASN1_WRITE_C", -#endif /* MBEDTLS_ASN1_WRITE_C */ -#if defined(MBEDTLS_BASE64_C) - "MBEDTLS_BASE64_C", -#endif /* MBEDTLS_BASE64_C */ -#if defined(MBEDTLS_BIGNUM_C) - "MBEDTLS_BIGNUM_C", -#endif /* MBEDTLS_BIGNUM_C */ -#if defined(MBEDTLS_BLOWFISH_C) - "MBEDTLS_BLOWFISH_C", -#endif /* MBEDTLS_BLOWFISH_C */ -#if defined(MBEDTLS_CAMELLIA_C) - "MBEDTLS_CAMELLIA_C", -#endif /* MBEDTLS_CAMELLIA_C */ -#if defined(MBEDTLS_CCM_C) - "MBEDTLS_CCM_C", -#endif /* MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CERTS_C) - "MBEDTLS_CERTS_C", -#endif /* MBEDTLS_CERTS_C */ -#if defined(MBEDTLS_CIPHER_C) - "MBEDTLS_CIPHER_C", -#endif /* MBEDTLS_CIPHER_C */ -#if defined(MBEDTLS_CMAC_C) - "MBEDTLS_CMAC_C", -#endif /* MBEDTLS_CMAC_C */ -#if defined(MBEDTLS_CTR_DRBG_C) - "MBEDTLS_CTR_DRBG_C", -#endif /* MBEDTLS_CTR_DRBG_C */ -#if defined(MBEDTLS_DEBUG_C) - "MBEDTLS_DEBUG_C", -#endif /* MBEDTLS_DEBUG_C */ -#if defined(MBEDTLS_DES_C) - "MBEDTLS_DES_C", -#endif /* MBEDTLS_DES_C */ -#if defined(MBEDTLS_DHM_C) - "MBEDTLS_DHM_C", -#endif /* MBEDTLS_DHM_C */ -#if defined(MBEDTLS_ECDH_C) - "MBEDTLS_ECDH_C", -#endif /* MBEDTLS_ECDH_C */ -#if defined(MBEDTLS_ECDSA_C) - "MBEDTLS_ECDSA_C", -#endif /* MBEDTLS_ECDSA_C */ -#if defined(MBEDTLS_ECJPAKE_C) - "MBEDTLS_ECJPAKE_C", -#endif /* MBEDTLS_ECJPAKE_C */ -#if defined(MBEDTLS_ECP_C) - "MBEDTLS_ECP_C", -#endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_ENTROPY_C) - "MBEDTLS_ENTROPY_C", -#endif /* MBEDTLS_ENTROPY_C */ -#if defined(MBEDTLS_ERROR_C) - "MBEDTLS_ERROR_C", -#endif /* MBEDTLS_ERROR_C */ -#if defined(MBEDTLS_GCM_C) - "MBEDTLS_GCM_C", -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_HAVEGE_C) - "MBEDTLS_HAVEGE_C", -#endif /* MBEDTLS_HAVEGE_C */ -#if defined(MBEDTLS_HMAC_DRBG_C) - "MBEDTLS_HMAC_DRBG_C", -#endif /* MBEDTLS_HMAC_DRBG_C */ -#if defined(MBEDTLS_MD_C) - "MBEDTLS_MD_C", -#endif /* MBEDTLS_MD_C */ -#if defined(MBEDTLS_MD2_C) - "MBEDTLS_MD2_C", -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - "MBEDTLS_MD4_C", -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - "MBEDTLS_MD5_C", -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) - "MBEDTLS_MEMORY_BUFFER_ALLOC_C", -#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ -#if defined(MBEDTLS_NET_C) - "MBEDTLS_NET_C", -#endif /* MBEDTLS_NET_C */ -#if defined(MBEDTLS_OID_C) - "MBEDTLS_OID_C", -#endif /* MBEDTLS_OID_C */ -#if defined(MBEDTLS_PADLOCK_C) - "MBEDTLS_PADLOCK_C", -#endif /* MBEDTLS_PADLOCK_C */ -#if defined(MBEDTLS_PEM_PARSE_C) - "MBEDTLS_PEM_PARSE_C", -#endif /* MBEDTLS_PEM_PARSE_C */ -#if defined(MBEDTLS_PEM_WRITE_C) - "MBEDTLS_PEM_WRITE_C", -#endif /* MBEDTLS_PEM_WRITE_C */ -#if defined(MBEDTLS_PK_C) - "MBEDTLS_PK_C", -#endif /* MBEDTLS_PK_C */ -#if defined(MBEDTLS_PK_PARSE_C) - "MBEDTLS_PK_PARSE_C", -#endif /* MBEDTLS_PK_PARSE_C */ -#if defined(MBEDTLS_PK_WRITE_C) - "MBEDTLS_PK_WRITE_C", -#endif /* MBEDTLS_PK_WRITE_C */ -#if defined(MBEDTLS_PKCS5_C) - "MBEDTLS_PKCS5_C", -#endif /* MBEDTLS_PKCS5_C */ -#if defined(MBEDTLS_PKCS11_C) - "MBEDTLS_PKCS11_C", -#endif /* MBEDTLS_PKCS11_C */ -#if defined(MBEDTLS_PKCS12_C) - "MBEDTLS_PKCS12_C", -#endif /* MBEDTLS_PKCS12_C */ -#if defined(MBEDTLS_PLATFORM_C) - "MBEDTLS_PLATFORM_C", -#endif /* MBEDTLS_PLATFORM_C */ -#if defined(MBEDTLS_RIPEMD160_C) - "MBEDTLS_RIPEMD160_C", -#endif /* MBEDTLS_RIPEMD160_C */ -#if defined(MBEDTLS_RSA_C) - "MBEDTLS_RSA_C", -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_SHA1_C) - "MBEDTLS_SHA1_C", -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - "MBEDTLS_SHA256_C", -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - "MBEDTLS_SHA512_C", -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_SSL_CACHE_C) - "MBEDTLS_SSL_CACHE_C", -#endif /* MBEDTLS_SSL_CACHE_C */ -#if defined(MBEDTLS_SSL_COOKIE_C) - "MBEDTLS_SSL_COOKIE_C", -#endif /* MBEDTLS_SSL_COOKIE_C */ -#if defined(MBEDTLS_SSL_TICKET_C) - "MBEDTLS_SSL_TICKET_C", -#endif /* MBEDTLS_SSL_TICKET_C */ -#if defined(MBEDTLS_SSL_CLI_C) - "MBEDTLS_SSL_CLI_C", -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - "MBEDTLS_SSL_SRV_C", -#endif /* MBEDTLS_SSL_SRV_C */ -#if defined(MBEDTLS_SSL_TLS_C) - "MBEDTLS_SSL_TLS_C", -#endif /* MBEDTLS_SSL_TLS_C */ -#if defined(MBEDTLS_THREADING_C) - "MBEDTLS_THREADING_C", -#endif /* MBEDTLS_THREADING_C */ -#if defined(MBEDTLS_TIMING_C) - "MBEDTLS_TIMING_C", -#endif /* MBEDTLS_TIMING_C */ -#if defined(MBEDTLS_VERSION_C) - "MBEDTLS_VERSION_C", -#endif /* MBEDTLS_VERSION_C */ -#if defined(MBEDTLS_X509_USE_C) - "MBEDTLS_X509_USE_C", -#endif /* MBEDTLS_X509_USE_C */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - "MBEDTLS_X509_CRT_PARSE_C", -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_X509_CRL_PARSE_C) - "MBEDTLS_X509_CRL_PARSE_C", -#endif /* MBEDTLS_X509_CRL_PARSE_C */ -#if defined(MBEDTLS_X509_CSR_PARSE_C) - "MBEDTLS_X509_CSR_PARSE_C", -#endif /* MBEDTLS_X509_CSR_PARSE_C */ -#if defined(MBEDTLS_X509_CREATE_C) - "MBEDTLS_X509_CREATE_C", -#endif /* MBEDTLS_X509_CREATE_C */ -#if defined(MBEDTLS_X509_CRT_WRITE_C) - "MBEDTLS_X509_CRT_WRITE_C", -#endif /* MBEDTLS_X509_CRT_WRITE_C */ -#if defined(MBEDTLS_X509_CSR_WRITE_C) - "MBEDTLS_X509_CSR_WRITE_C", -#endif /* MBEDTLS_X509_CSR_WRITE_C */ -#if defined(MBEDTLS_XTEA_C) - "MBEDTLS_XTEA_C", -#endif /* MBEDTLS_XTEA_C */ -#endif /* MBEDTLS_VERSION_FEATURES */ - NULL -}; - -int mbedtls_version_check_feature( const char *feature ) -{ - const char **idx = features; - - if( *idx == NULL ) - return( -2 ); - - if( feature == NULL ) - return( -1 ); - - while( *idx != NULL ) - { - if( !strcmp( *idx, feature ) ) - return( 0 ); - idx++; - } - return( -1 ); -} - -#endif /* MBEDTLS_VERSION_C */ diff --git a/components/security/mbedtls/src/x509.c b/components/security/mbedtls/src/x509.c deleted file mode 100644 index f6e6a20a..00000000 --- a/components/security/mbedtls/src/x509.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * X.509 common functions for parsing and verification - * - * 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) - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_USE_C) - -#include "mbedtls/x509.h" -#include "mbedtls/asn1.h" -#include "mbedtls/oid.h" -#include "mbedtls/debug.h" - -#include -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_printf printf -#define mbedtls_snprintf snprintf -#endif - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include -#else -#include -#endif - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } -#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } - -#if defined(MBEDTLS_IOT_SPECIFIC) -static unsigned char CRT_OID_PKCS1_MD5[] = { - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04 -}; -static unsigned char CRT_OID_PKCS1_SHA1[] = { - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 -}; -static unsigned char CRT_OID_PKCS1_SHA256[] = { - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b -}; -#endif - -/* - * CertificateSerialNumber ::= INTEGER - */ -int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *serial ) -{ - int ret; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_SERIAL + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && - **p != MBEDTLS_ASN1_INTEGER ) - return( MBEDTLS_ERR_X509_INVALID_SERIAL + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - serial->tag = *(*p)++; - - if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); - - serial->p = *p; - *p += serial->len; - - return( 0 ); -} - -/* Get an algorithm identifier without parameters (eg for signatures) - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - */ -int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - return( 0 ); -} - -/* - * Parse an algorithm identifier with (optional) paramaters - */ -int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - return( 0 ); -} - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) -/* - * HashAlgorithm ::= AlgorithmIdentifier - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - * - * For HashAlgorithm, parameters MUST be NULL or absent. - */ -static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) -{ - int ret; - unsigned char *p; - const unsigned char *end; - mbedtls_x509_buf md_oid; - size_t len; - - /* Make sure we got a SEQUENCE and setup bounds */ - if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - p = (unsigned char *) alg->p; - end = p + alg->len; - - if( p >= end ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - /* Parse md_oid */ - md_oid.tag = *p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - md_oid.p = p; - p += md_oid.len; - - /* Get md_alg from md_oid */ - if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - /* Make sure params is absent of NULL */ - if( p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * RSASSA-PSS-params ::= SEQUENCE { - * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, - * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, - * saltLength [2] INTEGER DEFAULT 20, - * trailerField [3] INTEGER DEFAULT 1 } - * -- Note that the tags in this Sequence are explicit. - * - * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value - * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other - * option. Enfore this at parsing time. - */ -int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, - mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, - int *salt_len ) -{ - int ret; - unsigned char *p; - const unsigned char *end, *end2; - size_t len; - mbedtls_x509_buf alg_id, alg_params; - - /* First set everything to defaults */ - *md_alg = MBEDTLS_MD_SHA1; - *mgf_md = MBEDTLS_MD_SHA1; - *salt_len = 20; - - /* Make sure params is a SEQUENCE and setup bounds */ - if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - p = (unsigned char *) params->p; - end = p + params->len; - - if( p == end ) - return( 0 ); - - /* - * HashAlgorithm - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) - { - end2 = p + len; - - /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ - if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end2 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p == end ) - return( 0 ); - - /* - * MaskGenAlgorithm - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) - { - end2 = p + len; - - /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ - if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) - return( ret ); - - /* Only MFG1 is recognised for now */ - if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) - return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + - MBEDTLS_ERR_OID_NOT_FOUND ); - - /* Parse HashAlgorithm */ - if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) - return( ret ); - - if( p != end2 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p == end ) - return( 0 ); - - /* - * salt_len - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) - { - end2 = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end2 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p == end ) - return( 0 ); - - /* - * trailer_field (if present, must be 1) - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) - { - int trailer_field; - - end2 = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end2 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( trailer_field != 1 ) - return( MBEDTLS_ERR_X509_INVALID_ALG ); - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} -#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ - -/* - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - */ -static int x509_get_attr_type_value( unsigned char **p, - const unsigned char *end, - mbedtls_x509_name *cur ) -{ - int ret; - size_t len; - mbedtls_x509_buf *oid; - mbedtls_x509_buf *val; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - oid = &cur->oid; - oid->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); - - oid->p = *p; - *p += oid->len; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && - **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && - **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && - **p != MBEDTLS_ASN1_BIT_STRING ) - return( MBEDTLS_ERR_X509_INVALID_NAME + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - val = &cur->val; - val->tag = *(*p)++; - - if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); - - val->p = *p; - *p += val->len; - - cur->next = NULL; - - return( 0 ); -} - -/* - * Name ::= CHOICE { -- only one possibility for now -- - * rdnSequence RDNSequence } - * - * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName - * - * RelativeDistinguishedName ::= - * SET OF AttributeTypeAndValue - * - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - * - * The data structure is optimized for the common case where each RDN has only - * one element, which is represented as a list of AttributeTypeAndValue. - * For the general case we still use a flat list, but we mark elements of the - * same set so that they are "merged" together in the functions that consume - * this list, eg mbedtls_x509_dn_gets(). - */ -int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, - mbedtls_x509_name *cur ) -{ - int ret; - size_t set_len; - const unsigned char *end_set; - - /* don't use recursion, we'd risk stack overflow if not optimized */ - while( 1 ) - { - /* - * parse SET - */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); - - end_set = *p + set_len; - - while( 1 ) - { - if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) - return( ret ); - - if( *p == end_set ) - break; - - /* Mark this item as being no the only one in a set */ - cur->next_merged = 1; - - cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - cur = cur->next; - } - - /* - * continue until end of SEQUENCE is reached - */ - if( *p == end ) - return( 0 ); - - cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - cur = cur->next; - } -} - -static int x509_parse_int( unsigned char **p, size_t n, int *res ) -{ - *res = 0; - - for( ; n > 0; --n ) - { - if( ( **p < '0') || ( **p > '9' ) ) - return ( MBEDTLS_ERR_X509_INVALID_DATE ); - - *res *= 10; - *res += ( *(*p)++ - '0' ); - } - - return( 0 ); -} - -static int x509_date_is_valid(const mbedtls_x509_time *time) -{ - int ret = MBEDTLS_ERR_X509_INVALID_DATE; - - CHECK_RANGE( 0, 9999, time->year ); - CHECK_RANGE( 0, 23, time->hour ); - CHECK_RANGE( 0, 59, time->min ); - CHECK_RANGE( 0, 59, time->sec ); - - switch( time->mon ) - { - case 1: case 3: case 5: case 7: case 8: case 10: case 12: - CHECK_RANGE( 1, 31, time->day ); - break; - case 4: case 6: case 9: case 11: - CHECK_RANGE( 1, 30, time->day ); - break; - case 2: - CHECK_RANGE( 1, 28 + (time->year % 4 == 0), time->day ); - break; - default: - return( ret ); - } - - return( 0 ); -} - -/* - * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) - * field. - */ -static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, - mbedtls_x509_time *time ) -{ - int ret; - - /* - * Minimum length is 10 or 12 depending on yearlen - */ - if ( len < yearlen + 8 ) - return ( MBEDTLS_ERR_X509_INVALID_DATE ); - len -= yearlen + 8; - - /* - * Parse year, month, day, hour, minute - */ - CHECK( x509_parse_int( p, yearlen, &time->year ) ); - if ( 2 == yearlen ) - { - if ( time->year < 50 ) - time->year += 100; - - time->year += 1900; - } - - CHECK( x509_parse_int( p, 2, &time->mon ) ); - CHECK( x509_parse_int( p, 2, &time->day ) ); - CHECK( x509_parse_int( p, 2, &time->hour ) ); - CHECK( x509_parse_int( p, 2, &time->min ) ); - - /* - * Parse seconds if present - */ - if ( len >= 2 ) - { - CHECK( x509_parse_int( p, 2, &time->sec ) ); - len -= 2; - } - else - return ( MBEDTLS_ERR_X509_INVALID_DATE ); - - /* - * Parse trailing 'Z' if present - */ - if ( 1 == len && 'Z' == **p ) - { - (*p)++; - len--; - } - - /* - * We should have parsed all characters at this point - */ - if ( 0 != len ) - return ( MBEDTLS_ERR_X509_INVALID_DATE ); - - CHECK( x509_date_is_valid( time ) ); - - return ( 0 ); -} - -/* - * Time ::= CHOICE { - * utcTime UTCTime, - * generalTime GeneralizedTime } - */ -int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, - mbedtls_x509_time *time ) -{ - int ret; - size_t len, year_len; - unsigned char tag; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - tag = **p; - - if( tag == MBEDTLS_ASN1_UTC_TIME ) - year_len = 2; - else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) - year_len = 4; - else - return( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - (*p)++; - ret = mbedtls_asn1_get_len( p, end, &len ); - - if( ret != 0 ) - return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); - - return x509_parse_time( p, len, year_len, time ); -} - -int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) -{ - int ret; - size_t len; - int tag_type; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - tag_type = **p; - - if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); - - sig->tag = tag_type; - sig->len = len; - sig->p = *p; - - *p += len; - - return( 0 ); -} - -/* - * Get signature algorithm from alg OID and optional parameters - */ -int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, - void **sig_opts ) -{ -#if !defined(MBEDTLS_IOT_SPECIFIC) - int ret; -#endif - - if( *sig_opts != NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_IOT_SPECIFIC) - *md_alg = MBEDTLS_MD_NONE; - *pk_alg = MBEDTLS_PK_NONE; - - if( sig_oid->len == CRT_OID_IDENT_LEN) { -#if defined(MBEDTLS_MD5_C) - if (!memcmp(sig_oid->p, CRT_OID_PKCS1_MD5, CRT_OID_IDENT_LEN)) { - *md_alg = MBEDTLS_MD_MD5; - *pk_alg = MBEDTLS_PK_RSA; - } -#endif /* MBEDTLS_MD5_C */ - -#if defined(MBEDTLS_SHA1_C) - if (!memcmp(sig_oid->p, CRT_OID_PKCS1_SHA1, CRT_OID_IDENT_LEN)) { - *md_alg = MBEDTLS_MD_SHA1; - *pk_alg = MBEDTLS_PK_RSA; - } -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - if (!memcmp(sig_oid->p, CRT_OID_PKCS1_SHA256, CRT_OID_IDENT_LEN)) { - *md_alg = MBEDTLS_MD_SHA256; - *pk_alg = MBEDTLS_PK_RSA; - } -#endif /* MBEDTLS_SHA256_C */ - } - - if (*md_alg == MBEDTLS_MD_NONE) { - MBEDTLS_ALT_DEBUG_BUF(2, "x509_sig_oid", sig_oid->p, sig_oid->len); - return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND ); - } - -#else - if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) { - return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); - } -#endif /* MBEDTLS_IOT_SPECIFIC */ - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) - { - mbedtls_pk_rsassa_pss_options *pss_opts; - - pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); - if( pss_opts == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - ret = mbedtls_x509_get_rsassa_pss_params( sig_params, - md_alg, - &pss_opts->mgf1_hash_id, - &pss_opts->expected_salt_len ); - if( ret != 0 ) - { - mbedtls_free( pss_opts ); - return( ret ); - } - - *sig_opts = (void *) pss_opts; - } - else -#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ - { - /* Make sure parameters are absent or NULL */ - if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || - sig_params->len != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG ); - } - - return( 0 ); -} - -/* - * X.509 Extensions (No parsing of extensions, pointer should - * be either manually updated or extensions should be parsed!) - */ -int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *ext, int tag ) -{ - int ret; - size_t len; - - if( *p == end ) - return( 0 ); - - ext->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) - return( ret ); - - ext->p = *p; - end = *p + ext->len; - - /* - * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension - * - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( end != *p + len ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -#if !defined(MBEDTLS_IOT_SPECIFIC) -/* - * Store the name in printable form into buf; no more - * than size characters will be written - */ -int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) -{ - int ret; - size_t i, n; - unsigned char c, merge = 0; - const mbedtls_x509_name *name; - const char *short_name = NULL; - char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; - - memset( s, 0, sizeof( s ) ); - - name = dn; - p = buf; - n = size; - - while( name != NULL ) - { - if( !name->oid.p ) - { - name = name->next; - continue; - } - - if( name != dn ) - { - ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); - - if( ret == 0 ) - ret = mbedtls_snprintf( p, n, "%s=", short_name ); - else - ret = mbedtls_snprintf( p, n, "\?\?=" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - for( i = 0; i < name->val.len; i++ ) - { - if( i >= sizeof( s ) - 1 ) - break; - - c = name->val.p[i]; - if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) - s[i] = '?'; - else s[i] = c; - } - s[i] = '\0'; - ret = mbedtls_snprintf( p, n, "%s", s ); - MBEDTLS_X509_SAFE_SNPRINTF; - - merge = name->next_merged; - name = name->next; - } - - return( (int) ( size - n ) ); -} -#endif - -/* - * Store the serial in printable form into buf; no more - * than size characters will be written - */ -int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) -{ - int ret; - size_t i, n, nr; - char *p; - - p = buf; - n = size; - - nr = ( serial->len <= 32 ) - ? serial->len : 28; - - for( i = 0; i < nr; i++ ) - { - if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) - continue; - - ret = mbedtls_snprintf( p, n, "%02X%s", - serial->p[i], ( i < nr - 1 ) ? ":" : "" ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - if( nr != serial->len ) - { - ret = mbedtls_snprintf( p, n, "...." ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - return( (int) ( size - n ) ); -} - -#if !defined(MBEDTLS_IOT_SPECIFIC) -/* - * Helper for writing signature algorithms - */ -int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, - mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const void *sig_opts ) -{ - int ret; - char *p = buf; - size_t n = size; - const char *desc = NULL; - - ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); - if( ret != 0 ) - ret = mbedtls_snprintf( p, n, "???" ); - else - ret = mbedtls_snprintf( p, n, "%s", desc ); - MBEDTLS_X509_SAFE_SNPRINTF; - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) - { - const mbedtls_pk_rsassa_pss_options *pss_opts; - const mbedtls_md_info_t *md_info, *mgf_md_info; - - pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; - - md_info = mbedtls_md_info_from_type( md_alg ); - mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); - - ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", - md_info ? mbedtls_md_get_name( md_info ) : "???", - mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", - pss_opts->expected_salt_len ); - MBEDTLS_X509_SAFE_SNPRINTF; - } -#else - ((void) pk_alg); - ((void) md_alg); - ((void) sig_opts); -#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ - - return( (int)( size - n ) ); -} -#endif /* MBEDTLS_IOT_SPECIFIC */ - -/* - * Helper for writing "RSA key size", "EC key size", etc - */ -int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) -{ - char *p = buf; - size_t n = buf_size; - int ret; - - ret = mbedtls_snprintf( p, n, "%s key size", name ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( 0 ); -} - -#if defined(MBEDTLS_HAVE_TIME_DATE) -/* - * Set the time structure to the current time. - * Return 0 on success, non-zero on failure. - */ -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -static int x509_get_current_time( mbedtls_x509_time *now ) -{ - SYSTEMTIME st; - - GetSystemTime( &st ); - - now->year = st.wYear; - now->mon = st.wMonth; - now->day = st.wDay; - now->hour = st.wHour; - now->min = st.wMinute; - now->sec = st.wSecond; - - return( 0 ); -} -#else -static int x509_get_current_time( mbedtls_x509_time *now ) -{ - struct tm *lt; - mbedtls_time_t tt; - int ret = 0; - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - tt = mbedtls_time( NULL ); - lt = gmtime( &tt ); - - if( lt == NULL ) - ret = -1; - else - { - now->year = lt->tm_year + 1900; - now->mon = lt->tm_mon + 1; - now->day = lt->tm_mday; - now->hour = lt->tm_hour; - now->min = lt->tm_min; - now->sec = lt->tm_sec; - } - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} -#endif /* _WIN32 && !EFIX64 && !EFI32 */ - -/* - * Return 0 if before <= after, 1 otherwise - */ -static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) -{ - if( before->year > after->year ) - return( 1 ); - - if( before->year == after->year && - before->mon > after->mon ) - return( 1 ); - - if( before->year == after->year && - before->mon == after->mon && - before->day > after->day ) - return( 1 ); - - if( before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour > after->hour ) - return( 1 ); - - if( before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour == after->hour && - before->min > after->min ) - return( 1 ); - - if( before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour == after->hour && - before->min == after->min && - before->sec > after->sec ) - return( 1 ); - - return( 0 ); -} - -int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) -{ - mbedtls_x509_time now; - - if( x509_get_current_time( &now ) != 0 ) - return( 1 ); - - return( x509_check_time( &now, to ) ); -} - -int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) -{ - mbedtls_x509_time now; - - if( x509_get_current_time( &now ) != 0 ) - return( 1 ); - - return( x509_check_time( from, &now ) ); -} - -#else /* MBEDTLS_HAVE_TIME_DATE */ - -int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) -{ - ((void) to); - return( 0 ); -} - -int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) -{ - ((void) from); - return( 0 ); -} -#endif /* MBEDTLS_HAVE_TIME_DATE */ - -#if defined(MBEDTLS_SELF_TEST) - -#include "mbedtls/x509_crt.h" -#include "mbedtls/certs.h" - -/* - * Checkup routine - */ -int mbedtls_x509_self_test( int verbose ) -{ -#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA1_C) - int ret; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - - if( verbose != 0 ) - mbedtls_printf( " X.509 certificate load: " ); - - mbedtls_x509_crt_init( &clicert ); - - ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, - mbedtls_test_cli_crt_len ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( ret ); - } - - mbedtls_x509_crt_init( &cacert ); - - ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, - mbedtls_test_ca_crt_len ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n X.509 signature verify: "); - - ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n\n"); - - mbedtls_x509_crt_free( &cacert ); - mbedtls_x509_crt_free( &clicert ); - - return( 0 ); -#else - ((void) verbose); - return( 0 ); -#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_X509_USE_C */ diff --git a/components/security/mbedtls/src/x509_create.c b/components/security/mbedtls/src/x509_create.c deleted file mode 100644 index df20ec8e..00000000 --- a/components/security/mbedtls/src/x509_create.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * X.509 base functions for creating certificates / CSRs - * - * 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_X509_CREATE_C) - -#include "mbedtls/x509.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/oid.h" - -#include - -typedef struct { - const char *name; - size_t name_len; - const char*oid; -} x509_attr_descriptor_t; - -#define ADD_STRLEN( s ) s, sizeof( s ) - 1 - -static const x509_attr_descriptor_t x509_attrs[] = -{ - { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, - { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, - { ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY }, - { ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY }, - { ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION }, - { ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION }, - { ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY }, - { ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY }, - { ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL }, - { ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT }, - { ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT }, - { ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE }, - { ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE }, - { ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL }, - { ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER }, - { ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS }, - { ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE }, - { ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER }, - { ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE }, - { ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME }, - { ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME }, - { ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME }, - { ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME }, - { ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS }, - { ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM }, - { ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER }, - { ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT }, - { ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT }, - { NULL, 0, NULL } -}; - -static const char *x509_at_oid_from_name( const char *name, size_t name_len ) -{ - const x509_attr_descriptor_t *cur; - - for( cur = x509_attrs; cur->name != NULL; cur++ ) - if( cur->name_len == name_len && - strncmp( cur->name, name, name_len ) == 0 ) - break; - - return( cur->oid ); -} - -int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) -{ - int ret = 0; - const char *s = name, *c = s; - const char *end = s + strlen( s ); - const char *oid = NULL; - int in_tag = 1; - char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; - char *d = data; - - /* Clear existing chain if present */ - mbedtls_asn1_free_named_data_list( head ); - - while( c <= end ) - { - if( in_tag && *c == '=' ) - { - if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) - { - ret = MBEDTLS_ERR_X509_UNKNOWN_OID; - goto exit; - } - - s = c + 1; - in_tag = 0; - d = data; - } - - if( !in_tag && *c == '\\' && c != end ) - { - c++; - - /* Check for valid escaped characters */ - if( c == end || *c != ',' ) - { - ret = MBEDTLS_ERR_X509_INVALID_NAME; - goto exit; - } - } - else if( !in_tag && ( *c == ',' || c == end ) ) - { - if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ), - (unsigned char *) data, - d - data ) == NULL ) - { - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - } - - while( c < end && *(c + 1) == ' ' ) - c++; - - s = c + 1; - in_tag = 1; - } - - if( !in_tag && s != c + 1 ) - { - *(d++) = *c; - - if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) - { - ret = MBEDTLS_ERR_X509_INVALID_NAME; - goto exit; - } - } - - c++; - } - -exit: - - return( ret ); -} - -/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved - * to store the critical boolean for us - */ -int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, - int critical, const unsigned char *val, size_t val_len ) -{ - mbedtls_asn1_named_data *cur; - - if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, - NULL, val_len + 1 ) ) == NULL ) - { - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - } - - cur->val.p[0] = critical; - memcpy( cur->val.p + 1, val, val_len ); - - return( 0 ); -} - -/* - * RelativeDistinguishedName ::= - * SET OF AttributeTypeAndValue - * - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - */ -static int x509_write_name( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - const unsigned char *name, size_t name_len ) -{ - int ret; - size_t len = 0; - - // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL - // - if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len && - memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start, - (const char *) name, - name_len ) ); - } - else - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start, - (const char *) name, - name_len ) ); - } - - // Write OID - // - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SET ) ); - - return( (int) len ); -} - -int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ) -{ - int ret; - size_t len = 0; - mbedtls_asn1_named_data *cur = first; - - while( cur != NULL ) - { - MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, - cur->oid.len, - cur->val.p, cur->val.len ) ); - cur = cur->next; - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - unsigned char *sig, size_t size ) -{ - int ret; - size_t len = 0; - - if( *p < start || (size_t)( *p - start ) < size ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len = size; - (*p) -= len; - memcpy( *p, sig, len ); - - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0; - len += 1; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); - - // Write OID - // - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, - oid_len, 0 ) ); - - return( (int) len ); -} - -static int x509_write_extension( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *ext ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, - ext->val.len - 1 ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); - - if( ext->val.p[0] != 0 ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, - ext->oid.len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -/* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING - * -- contains the DER encoding of an ASN.1 value - * -- corresponding to the extension type identified - * -- by extnID - * } - */ -int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ) -{ - int ret; - size_t len = 0; - mbedtls_asn1_named_data *cur_ext = first; - - while( cur_ext != NULL ) - { - MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); - cur_ext = cur_ext->next; - } - - return( (int) len ); -} - -#endif /* MBEDTLS_X509_CREATE_C */ diff --git a/components/security/mbedtls/src/x509_crl.c b/components/security/mbedtls/src/x509_crl.c deleted file mode 100644 index 927f3037..00000000 --- a/components/security/mbedtls/src/x509_crl.c +++ /dev/null @@ -1,725 +0,0 @@ -/* - * X.509 Certidicate Revocation List (CRL) parsing - * - * 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) - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CRL_PARSE_C) - -#include "mbedtls/x509_crl.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_snprintf snprintf -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include -#else -#include -#endif - -#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) -#include -#endif - -/* 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; -} - -/* - * Version ::= INTEGER { v1(0), v2(1) } - */ -static int x509_crl_get_version( unsigned char **p, - const unsigned char *end, - int *ver ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - *ver = 0; - return( 0 ); - } - - return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); - } - - return( 0 ); -} - -/* - * X.509 CRL v2 extensions (no extensions parsed yet.) - */ -static int x509_get_crl_ext( unsigned char **p, - const unsigned char *end, - mbedtls_x509_buf *ext ) -{ - int ret; - size_t len = 0; - - /* Get explicit tag */ - if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - while( *p < end ) - { - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - *p += len; - } - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 CRL v2 entry extensions (no extensions parsed yet.) - */ -static int x509_get_crl_entry_ext( unsigned char **p, - const unsigned char *end, - mbedtls_x509_buf *ext ) -{ - int ret; - size_t len = 0; - - /* OPTIONAL */ - if( end <= *p ) - return( 0 ); - - ext->tag = **p; - ext->p = *p; - - /* - * Get CRL-entry extension sequence header - * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 - */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - ext->p = NULL; - return( 0 ); - } - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - } - - end = *p + ext->len; - - if( end != *p + ext->len ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - *p += len; - } - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 CRL Entries - */ -static int x509_get_entries( unsigned char **p, - const unsigned char *end, - mbedtls_x509_crl_entry *entry ) -{ - int ret; - size_t entry_len; - mbedtls_x509_crl_entry *cur_entry = entry; - - if( *p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - end = *p + entry_len; - - while( *p < end ) - { - size_t len2; - const unsigned char *end2; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) - { - return( ret ); - } - - cur_entry->raw.tag = **p; - cur_entry->raw.p = *p; - cur_entry->raw.len = len2; - end2 = *p + len2; - - if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_x509_get_time( p, end2, - &cur_entry->revocation_date ) ) != 0 ) - return( ret ); - - if( ( ret = x509_get_crl_entry_ext( p, end2, - &cur_entry->entry_ext ) ) != 0 ) - return( ret ); - - if( *p < end ) - { - cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); - - if( cur_entry->next == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - cur_entry = cur_entry->next; - } - } - - return( 0 ); -} - -/* - * Parse one CRLs in DER format and append it to the chained list - */ -int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, - const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; - mbedtls_x509_crl *crl = chain; - - /* - * Check for valid input - */ - if( crl == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); - memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); - memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); - - /* - * Add new CRL on the end of the chain if needed. - */ - while( crl->version != 0 && crl->next != NULL ) - crl = crl->next; - - if( crl->version != 0 && crl->next == NULL ) - { - crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); - - if( crl->next == NULL ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - } - - mbedtls_x509_crl_init( crl->next ); - crl = crl->next; - } - - /* - * Copy raw DER-encoded CRL - */ - if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - crl->raw.p = p; - crl->raw.len = buflen; - - end = p + buflen; - - /* - * CertificateList ::= SEQUENCE { - * tbsCertList TBSCertList, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT ); - } - - if( len != (size_t) ( end - p ) ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - /* - * TBSCertList ::= SEQUENCE { - */ - crl->tbs.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - end = p + len; - crl->tbs.len = end - crl->tbs.p; - - /* - * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } - * -- if present, MUST be v2 - * - * signature AlgorithmIdentifier - */ - if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || - ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - crl->version++; - - if( crl->version > 2 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); - } - - if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, - &crl->sig_md, &crl->sig_pk, - &crl->sig_opts ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); - } - - /* - * issuer Name - */ - crl->issuer_raw.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - crl->issuer_raw.len = p - crl->issuer_raw.p; - - /* - * thisUpdate Time - * nextUpdate Time OPTIONAL - */ - if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) - { - if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && - ret != ( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - } - - /* - * revokedCertificates SEQUENCE OF SEQUENCE { - * userCertificate CertificateSerialNumber, - * revocationDate Time, - * crlEntryExtensions Extensions OPTIONAL - * -- if present, MUST be v2 - * } OPTIONAL - */ - if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - /* - * crlExtensions EXPLICIT Extensions OPTIONAL - * -- if present, MUST be v2 - */ - if( crl->version == 2 ) - { - ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); - - if( ret != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - } - - if( p != end ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - end = crl->raw.p + crl->raw.len; - - /* - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - */ - if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - if( crl->sig_oid.len != sig_oid2.len || - memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || - sig_params1.len != sig_params2.len || - ( sig_params1.len != 0 && - memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_SIG_MISMATCH ); - } - - if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - if( p != end ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - return( 0 ); -} - -/* - * Parse one or more CRLs and add them to the chained list - */ -int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) -{ -#if defined(MBEDTLS_PEM_PARSE_C) - int ret; - size_t use_len; - mbedtls_pem_context pem; - int is_pem = 0; - - if( chain == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - do - { - mbedtls_pem_init( &pem ); - - // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated - // string - if( buflen == 0 || buf[buflen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN X509 CRL-----", - "-----END X509 CRL-----", - buf, NULL, 0, &use_len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - is_pem = 1; - - buflen -= use_len; - buf += use_len; - - if( ( ret = mbedtls_x509_crl_parse_der( chain, - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } - } - else if( is_pem ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } - - mbedtls_pem_free( &pem ); - } - /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. - * And a valid CRL cannot be less than 1 byte anyway. */ - while( is_pem && buflen > 1 ); - - if( is_pem ) - return( 0 ); - else -#endif /* MBEDTLS_PEM_PARSE_C */ - return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load one or more CRLs and add them to the chained list - */ -int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_x509_crl_parse( chain, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -/* - * Return an informational string about the certificate. - */ -#define BEFORE_COLON 14 -#define BC "14" -/* - * Return an informational string about the CRL. - */ -int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crl *crl ) -{ - int ret; - size_t n; - char *p; - const mbedtls_x509_crl_entry *entry; - - p = buf; - n = size; - - ret = mbedtls_snprintf( p, n, "%sCRL version : %d", - prefix, crl->version ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crl->this_update.year, crl->this_update.mon, - crl->this_update.day, crl->this_update.hour, - crl->this_update.min, crl->this_update.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%snext update : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crl->next_update.year, crl->next_update.mon, - crl->next_update.day, crl->next_update.hour, - crl->next_update.min, crl->next_update.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - entry = &crl->entry; - - ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", - prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - while( entry != NULL && entry->raw.len != 0 ) - { - ret = mbedtls_snprintf( p, n, "\n%sserial number: ", - prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, " revocation date: " \ - "%04d-%02d-%02d %02d:%02d:%02d", - entry->revocation_date.year, entry->revocation_date.mon, - entry->revocation_date.day, entry->revocation_date.hour, - entry->revocation_date.min, entry->revocation_date.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - entry = entry->next; - } - -#if !defined(MBEDTLS_IOT_SPECIFIC) - ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, - crl->sig_opts ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n" ); - MBEDTLS_X509_SAFE_SNPRINTF; -#endif /* MBEDTLS_IOT_SPECIFIC */ - - return( (int) ( size - n ) ); -} - -/* - * Initialize a CRL chain - */ -void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) -{ - memset( crl, 0, sizeof(mbedtls_x509_crl) ); -} - -/* - * Unallocate all CRL data - */ -void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) -{ - mbedtls_x509_crl *crl_cur = crl; - mbedtls_x509_crl *crl_prv; - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - mbedtls_x509_crl_entry *entry_cur; - mbedtls_x509_crl_entry *entry_prv; - - if( crl == NULL ) - return; - - do - { -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - mbedtls_free( crl_cur->sig_opts ); -#endif - - name_cur = crl_cur->issuer.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); - mbedtls_free( name_prv ); - } - - entry_cur = crl_cur->entry.next; - while( entry_cur != NULL ) - { - entry_prv = entry_cur; - entry_cur = entry_cur->next; - mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); - mbedtls_free( entry_prv ); - } - - if( crl_cur->raw.p != NULL ) - { - mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len ); - mbedtls_free( crl_cur->raw.p ); - } - - crl_cur = crl_cur->next; - } - while( crl_cur != NULL ); - - crl_cur = crl; - do - { - crl_prv = crl_cur; - crl_cur = crl_cur->next; - - mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); - if( crl_prv != crl ) - mbedtls_free( crl_prv ); - } - while( crl_cur != NULL ); -} - -#endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/components/security/mbedtls/src/x509_crt.c b/components/security/mbedtls/src/x509_crt.c deleted file mode 100644 index e3edfca8..00000000 --- a/components/security/mbedtls/src/x509_crt.c +++ /dev/null @@ -1,2463 +0,0 @@ -/* - * X.509 certificate parsing and verification - * - * 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) - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - -#include "mbedtls/x509_crt.h" -#include "mbedtls/oid.h" - -#include -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_snprintf snprintf -#define mbedtls_printf(_f, _a ...) \ - printf("%s %d: "_f, __FUNCTION__, __LINE__, ##_a) -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include -#else -#include -#endif - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -/* 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; -} - -/* - * Default profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = -{ -#if defined(MBEDTLS_IOT_SPECIFIC) -#if defined(MBEDTLS_MD5_C) - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_MD5 ) | -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | -#endif /* MBEDTLS_SHA1_C */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ), - MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_RSA ), - 0, - 2048, -#else - /* Hashes from SHA-1 and above */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_MD5 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), - 0xFFFFFFF, /* Any PK alg */ - 0xFFFFFFF, /* Any curve */ - 1024, -#endif -}; - -/* - * Next-default profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = -{ - /* Hashes from SHA-256 and above */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), - 0xFFFFFFF, /* Any PK alg */ -#if defined(MBEDTLS_ECP_C) - /* Curves at or above 128-bit security level */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), -#else - 0, -#endif - 2048, -}; - -/* - * NSA Suite B Profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = -{ - /* Only SHA-256 and 384 */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), - /* Only ECDSA */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ), -#if defined(MBEDTLS_ECP_C) - /* Only NIST P-256 and P-384 */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), -#else - 0, -#endif - 0, -}; - -/* - * Check md_alg against profile - * Return 0 if md_alg acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, - mbedtls_md_type_t md_alg ) -{ - if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) - return( 0 ); - - return( -1 ); -} - -/* - * Check pk_alg against profile - * Return 0 if pk_alg acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg ) -{ - if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) - return( 0 ); - - return( -1 ); -} - -/* - * Check key against profile - * Return 0 if pk_alg acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg, - const mbedtls_pk_context *pk ) -{ -#if defined(MBEDTLS_RSA_C) - if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) - { - if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) - return( 0 ); - - return( -1 ); - } -#endif - -#if defined(MBEDTLS_ECP_C) - if( pk_alg == MBEDTLS_PK_ECDSA || - pk_alg == MBEDTLS_PK_ECKEY || - pk_alg == MBEDTLS_PK_ECKEY_DH ) - { - mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; - - if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) - return( 0 ); - - return( -1 ); - } -#endif - - return( -1 ); -} - -static int x509_skip_parse( unsigned char **p, - const unsigned char *end, - int tag ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - return( 0 ); - } - - return( ret ); - } - - *p += len; - - return( 0 ); -} - -/* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ -static int x509_get_version( unsigned char **p, - const unsigned char *end, - int *ver ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - *ver = 0; - return( 0 ); - } - - return( ret ); - } - - end = *p + len; - - if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_VERSION + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -#if defined(MBEDTLS_HAVE_TIME_DATE) -/* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - */ -static int x509_get_dates( unsigned char **p, - const unsigned char *end, - mbedtls_x509_time *from, - mbedtls_x509_time *to ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); - - end = *p + len; - - if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) - return( ret ); - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} -#endif /* MBEDTLS_HAVE_TIME_DATE */ - -#if !defined(MBEDTLS_IOT_SPECIFIC) -/* - * X.509 v2/v3 unique identifier (not parsed) - */ -static int x509_get_uid( unsigned char **p, - const unsigned char *end, - mbedtls_x509_buf *uid, int n ) -{ - int ret; - - if( *p == end ) - return( 0 ); - - uid->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - uid->p = *p; - *p += uid->len; - - return( 0 ); -} -#endif /* MBEDTLS_IOT_SPECIFIC */ - -static int x509_get_basic_constraints( unsigned char **p, - const unsigned char *end, - int *ca_istrue, - int *max_pathlen ) -{ - int ret; - size_t len; - - /* - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - */ - *ca_istrue = 0; /* DEFAULT FALSE */ - *max_pathlen = 0; /* endless */ - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( *p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - ret = mbedtls_asn1_get_int( p, end, ca_istrue ); - - if( ret != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( *ca_istrue != 0 ) - *ca_istrue = 1; - } - - if( *p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - (*max_pathlen)++; - - return( 0 ); -} - -static int x509_get_ns_cert_type( unsigned char **p, - const unsigned char *end, - unsigned char *ns_cert_type) -{ - int ret; - mbedtls_x509_bitstring bs = { 0, 0, NULL }; - - if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( bs.len != 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - /* Get actual bitstring */ - *ns_cert_type = *bs.p; - return( 0 ); -} - -static int x509_get_key_usage( unsigned char **p, - const unsigned char *end, - unsigned int *key_usage) -{ - int ret; - size_t i; - mbedtls_x509_bitstring bs = { 0, 0, NULL }; - - if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( bs.len < 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - /* Get actual bitstring */ - *key_usage = 0; - for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) - { - *key_usage |= (unsigned int) bs.p[i] << (8*i); - } - - return( 0 ); -} - -/* - * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId - * - * KeyPurposeId ::= OBJECT IDENTIFIER - */ -static int x509_get_ext_key_usage( unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *ext_key_usage) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - /* Sequence length must be >= 1 */ - if( ext_key_usage->buf.p == NULL ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - return( 0 ); -} - -/* - * SubjectAltName ::= GeneralNames - * - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName, - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER } - * - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString OPTIONAL, - * partyName [1] DirectoryString } - * - * NOTE: we only parse and use dNSName at this point. - */ -static int x509_get_subject_alt_name( unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *subject_alt_name ) -{ - int ret; - size_t len, tag_len; - mbedtls_asn1_buf *buf; - unsigned char tag; - mbedtls_asn1_sequence *cur = subject_alt_name; - - /* Get main sequence tag */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - tag = **p; - (*p)++; - if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( ( tag & MBEDTLS_ASN1_CONTEXT_SPECIFIC ) != MBEDTLS_ASN1_CONTEXT_SPECIFIC ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - /* Skip everything but DNS name */ - if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) - { - *p += tag_len; - continue; - } - - /* Allocate and assign next pointer */ - if( cur->buf.p != NULL ) - { - if( cur->next != NULL ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); - - cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_ALLOC_FAILED ); - - cur = cur->next; - } - - buf = &(cur->buf); - buf->tag = tag; - buf->p = *p; - buf->len = tag_len; - *p += buf->len; - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 v3 extensions - * - */ -static int x509_get_crt_ext( unsigned char **p, - const unsigned char *end, - mbedtls_x509_crt *crt ) -{ - int ret; - size_t len; - unsigned char *end_ext_data, *end_ext_octet; - - if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - while( *p < end ) - { - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - mbedtls_x509_buf extn_oid = {0, 0, NULL}; - int is_critical = 0; /* DEFAULT FALSE */ - int ext_type = 0; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - end_ext_data = *p + len; - - /* Get extension ID */ - extn_oid.tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - extn_oid.p = *p; - *p += extn_oid.len; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - /* Get optional critical */ - if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && - ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - /* Data should be octet string type */ - if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, - MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - end_ext_octet = *p + len; - - if( end_ext_octet != end_ext_data ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - /* - * Detect supported extensions - */ - ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); - - if( ret != 0 ) - { - /* No parser found, skip extension */ - *p = end_ext_octet; - -#if !defined(MBEDTLS_IOT_SPECIFIC) -#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - if( is_critical ) - { - /* Data is marked as critical: fail */ - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - } -#endif -#endif - continue; - } - - /* Forbid repeated extensions */ - if( ( crt->ext_types & ext_type ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); - - crt->ext_types |= ext_type; - - switch( ext_type ) - { - case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: - /* Parse basic constraints */ - if( ( ret = x509_get_basic_constraints( p, end_ext_octet, - &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) - return( ret ); - break; - - case MBEDTLS_X509_EXT_KEY_USAGE: - /* Parse key usage */ - if( ( ret = x509_get_key_usage( p, end_ext_octet, - &crt->key_usage ) ) != 0 ) - return( ret ); - break; - - case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: - /* Parse extended key usage */ - if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, - &crt->ext_key_usage ) ) != 0 ) - return( ret ); - break; - - case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: - /* Parse subject alt name */ - if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, - &crt->subject_alt_names ) ) != 0 ) - return( ret ); - break; - - case MBEDTLS_X509_EXT_NS_CERT_TYPE: - /* Parse netscape certificate type */ - if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, - &crt->ns_cert_type ) ) != 0 ) - return( ret ); - break; - - default: - return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); - } - } - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * Parse and fill a single X.509 certificate in DER format - */ -static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf, - size_t buflen ) -{ - int ret; - size_t len; - unsigned char *p, *end, *crt_end; - mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; - - memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); - memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); - memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); - - /* - * Check for valid input - */ - if( crt == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - // Use the original buffer until we figure out actual length - p = (unsigned char*) buf; - len = buflen; - end = p + len; - - /* - * Certificate ::= SEQUENCE { - * tbsCertificate TBSCertificate, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT ); - } - - if( len > (size_t) ( end - p ) ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - crt_end = p + len; - - // Create and populate a new buffer for the raw field - crt->raw.len = crt_end - buf; - crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); - if( p == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - memcpy( p, buf, crt->raw.len ); - - // Direct pointers to the new buffer - p += crt->raw.len - len; - end = crt_end = p + len; - - /* - * TBSCertificate ::= SEQUENCE { - */ - crt->tbs.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - end = p + len; - crt->tbs.len = end - crt->tbs.p; - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - * - * CertificateSerialNumber ::= INTEGER - * - * signature AlgorithmIdentifier - */ - if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || - ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || - ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, - &sig_params1 ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - crt->version++; - - if( crt->version > 3 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); - } - - if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, - &crt->sig_md, &crt->sig_pk, - &crt->sig_opts ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - /* - * issuer Name - */ - crt->issuer_raw.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - crt->issuer_raw.len = p - crt->issuer_raw.p; - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - * - */ -#if defined(MBEDTLS_HAVE_TIME_DATE) - if( ( ret = x509_get_dates( &p, end, &crt->valid_from, - &crt->valid_to ) ) != 0 ) -#else - if( ( ret = x509_skip_parse( &p, end, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) -#endif - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - /* - * subject Name - */ - crt->subject_raw.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - crt->subject_raw.len = p - crt->subject_raw.p; - - /* - * SubjectPublicKeyInfo - */ - if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - /* - * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * extensions [3] EXPLICIT Extensions OPTIONAL - * -- If present, version shall be v3 - */ - if( crt->version == 2 || crt->version == 3 ) - { -#if !defined(MBEDTLS_IOT_SPECIFIC) - ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); -#else - ret = x509_skip_parse( &p, end, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ); -#endif - if( ret != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - } - - if( crt->version == 2 || crt->version == 3 ) - { -#if !defined(MBEDTLS_IOT_SPECIFIC) - ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); -#else - ret = x509_skip_parse( &p, end, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ); -#endif - if( ret != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - } - -#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) - if( crt->version == 3 ) -#endif - { - ret = x509_get_crt_ext( &p, end, crt ); - - if( ret != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - } - - if( p != end ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - end = crt_end; - - /* - * } - * -- end of TBSCertificate - * - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - */ - if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - if( crt->sig_oid.len != sig_oid2.len || - memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || - sig_params1.len != sig_params2.len || - ( sig_params1.len != 0 && - memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_SIG_MISMATCH ); - } - - if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - if( p != end ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - return( 0 ); -} - -/* - * Parse one X.509 certificate in DER format from a buffer and add them to a - * chained list - */ -int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, - size_t buflen ) -{ - int ret; - mbedtls_x509_crt *crt = chain, *prev = NULL; - - /* - * Check for valid input - */ - if( crt == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - while( crt->version != 0 && crt->next != NULL ) - { - prev = crt; - crt = crt->next; - } - - /* - * Add new certificate on the end of the chain if needed. - */ - if( crt->version != 0 && crt->next == NULL ) - { - crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - - if( crt->next == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - prev = crt; - mbedtls_x509_crt_init( crt->next ); - crt = crt->next; - } - - if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) - { - if( prev ) - prev->next = NULL; - - if( crt != chain ) - mbedtls_free( crt ); - - return( ret ); - } - - return( 0 ); -} - -/* - * Parse one or more PEM certificates from a buffer and add them to the chained - * list - */ -int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) -{ -#if defined(MBEDTLS_PEM_PARSE_C) - int success = 0, first_error = 0, total_failed = 0; - int buf_format = MBEDTLS_X509_FORMAT_DER; -#endif - - /* - * Check for valid input - */ - if( chain == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - /* - * Determine buffer content. Buffer contains either one DER certificate or - * one or more PEM certificates. - */ -#if defined(MBEDTLS_PEM_PARSE_C) - if( buflen != 0 && buf[buflen - 1] == '\0' && - strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) - { - buf_format = MBEDTLS_X509_FORMAT_PEM; - } - - if( buf_format == MBEDTLS_X509_FORMAT_DER ) - return mbedtls_x509_crt_parse_der( chain, buf, buflen ); -#else - return mbedtls_x509_crt_parse_der( chain, buf, buflen ); -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) - if( buf_format == MBEDTLS_X509_FORMAT_PEM ) - { - int ret; - mbedtls_pem_context pem; - - /* 1 rather than 0 since the terminating NULL byte is counted in */ - while( buflen > 1 ) - { - size_t use_len; - mbedtls_pem_init( &pem ); - - /* If we get there, we know the string is null-terminated */ - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN CERTIFICATE-----", - "-----END CERTIFICATE-----", - buf, NULL, 0, &use_len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - buflen -= use_len; - buf += use_len; - } - else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) - { - return( ret ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - - /* - * PEM header and footer were found - */ - buflen -= use_len; - buf += use_len; - - if( first_error == 0 ) - first_error = ret; - - total_failed++; - continue; - } - else - break; - - ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); - - mbedtls_pem_free( &pem ); - - if( ret != 0 ) - { - /* - * Quit parsing on a memory error - */ - if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) - return( ret ); - - if( first_error == 0 ) - first_error = ret; - - total_failed++; - continue; - } - - success = 1; - } - } - - if( success ) - return( total_failed ); - else if( first_error ) - return( first_error ); - else - return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); -#endif /* MBEDTLS_PEM_PARSE_C */ -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load one or more certificates and add them to the chained list - */ -int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_x509_crt_parse( chain, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} - -#if 0 -int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) -{ - int ret = 0; -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - int w_ret; - WCHAR szDir[MAX_PATH]; - char filename[MAX_PATH]; - char *p; - size_t len = strlen( path ); - - WIN32_FIND_DATAW file_data; - HANDLE hFind; - - if( len > MAX_PATH - 3 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - memset( szDir, 0, sizeof(szDir) ); - memset( filename, 0, MAX_PATH ); - memcpy( filename, path, len ); - filename[len++] = '\\'; - p = filename + len; - filename[len++] = '*'; - - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, - MAX_PATH - 3 ); - if( w_ret == 0 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - hFind = FindFirstFileW( szDir, &file_data ); - if( hFind == INVALID_HANDLE_VALUE ) - return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); - - len = MAX_PATH - len; - do - { - memset( p, 0, len ); - - if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) - continue; - - w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - lstrlenW( file_data.cFileName ), - p, (int) len - 1, - NULL, NULL ); - if( w_ret == 0 ) - return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); - - w_ret = mbedtls_x509_crt_parse_file( chain, filename ); - if( w_ret < 0 ) - ret++; - else - ret += w_ret; - } - while( FindNextFileW( hFind, &file_data ) != 0 ); - - if( GetLastError() != ERROR_NO_MORE_FILES ) - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - - FindClose( hFind ); -#else /* _WIN32 */ - int t_ret; - int snp_ret; - struct stat sb; - struct dirent *entry; - char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; - DIR *dir = opendir( path ); - - if( dir == NULL ) - return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); - -#if defined(MBEDTLS_THREADING_PTHREAD) - if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) - { - closedir( dir ); - return( ret ); - } -#endif - - while( ( entry = readdir( dir ) ) != NULL ) - { - snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, - "%s/%s", path, entry->d_name ); - - if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) - { - ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; - goto cleanup; - } - else if( stat( entry_name, &sb ) == -1 ) - { - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - goto cleanup; - } - - if( !S_ISREG( sb.st_mode ) ) - continue; - - // Ignore parse errors - // - t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); - if( t_ret < 0 ) - ret++; - else - ret += t_ret; - } - -cleanup: - closedir( dir ); - -#if defined(MBEDTLS_THREADING_PTHREAD) - if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) - ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; -#endif - -#endif /* _WIN32 */ - - return( ret ); -} -#endif -#endif /* MBEDTLS_FS_IO */ - -#if !defined(MBEDTLS_IOT_SPECIFIC) -static int x509_info_subject_alt_name( char **buf, size_t *size, - const mbedtls_x509_sequence *subject_alt_name ) -{ - size_t i; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = subject_alt_name; - const char *sep = ""; - size_t sep_len = 0; - - while( cur != NULL ) - { - if( cur->buf.len + sep_len >= n ) - { - *p = '\0'; - return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); - } - - n -= cur->buf.len + sep_len; - for( i = 0; i < sep_len; i++ ) - *p++ = sep[i]; - for( i = 0; i < cur->buf.len; i++ ) - *p++ = cur->buf.p[i]; - - sep = ", "; - sep_len = 2; - - cur = cur->next; - } - - *p = '\0'; - - *size = n; - *buf = p; - - return( 0 ); -} - -#define PRINT_ITEM(i) \ - { \ - ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ - MBEDTLS_X509_SAFE_SNPRINTF; \ - sep = ", "; \ - } - -#define CERT_TYPE(type,name) \ - if( ns_cert_type & type ) \ - PRINT_ITEM( name ); - -static int x509_info_cert_type( char **buf, size_t *size, - unsigned char ns_cert_type ) -{ - int ret; - size_t n = *size; - char *p = *buf; - const char *sep = ""; - - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); - - *size = n; - *buf = p; - - return( 0 ); -} - -#define KEY_USAGE(code,name) \ - if( key_usage & code ) \ - PRINT_ITEM( name ); - -static int x509_info_key_usage( char **buf, size_t *size, - unsigned int key_usage ) -{ - int ret; - size_t n = *size; - char *p = *buf; - const char *sep = ""; - - KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); - KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); - KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); - KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); - KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); - KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); - KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); - KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); - KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); - - *size = n; - *buf = p; - - return( 0 ); -} - -static int x509_info_ext_key_usage( char **buf, size_t *size, - const mbedtls_x509_sequence *extended_key_usage ) -{ - int ret; - const char *desc; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = extended_key_usage; - const char *sep = ""; - - while( cur != NULL ) - { - if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) - desc = "???"; - - ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); - MBEDTLS_X509_SAFE_SNPRINTF; - - sep = ", "; - - cur = cur->next; - } - - *size = n; - *buf = p; - - return( 0 ); -} -#endif /* MBEDTLS_IOT_SPECIFIC */ - -/* - * Return an informational string about the certificate. - */ -#define BEFORE_COLON 18 -#define BC "18" -int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crt *crt ) -{ - int ret; - size_t n; - char *p; - char key_size_str[BEFORE_COLON]; - - p = buf; - n = size; - - if( NULL == crt ) - { - ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( (int) ( size - n ) ); - } - - ret = mbedtls_snprintf( p, n, "%scert. version : %d\r\n", - prefix, crt->version ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_snprintf( p, n, "%sserial number : ", - prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); - MBEDTLS_X509_SAFE_SNPRINTF; - -#if !defined(MBEDTLS_IOT_SPECIFIC) - ret = mbedtls_snprintf( p, n, "\r\n%sissuer name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\r\n%ssubject name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); - MBEDTLS_X509_SAFE_SNPRINTF; -#endif - - ret = mbedtls_snprintf( p, n, "\r\n%sissued on : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crt->valid_from.year, crt->valid_from.mon, - crt->valid_from.day, crt->valid_from.hour, - crt->valid_from.min, crt->valid_from.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\r\n%sexpires on : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crt->valid_to.year, crt->valid_to.mon, - crt->valid_to.day, crt->valid_to.hour, - crt->valid_to.min, crt->valid_to.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - -#if !defined(MBEDTLS_IOT_SPECIFIC) - ret = mbedtls_snprintf( p, n, "\r\n%ssigned using : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, - crt->sig_md, crt->sig_opts ); - MBEDTLS_X509_SAFE_SNPRINTF; -#endif /* MBEDTLS_IOT_SPECIFIC */ - - /* Key size */ - if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, - mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) - { - return( ret ); - } - - ret = mbedtls_snprintf( p, n, "\r\n%s%-" BC "s: %d bits", prefix, key_size_str, - (int) mbedtls_pk_get_bitlen( &crt->pk ) ); - MBEDTLS_X509_SAFE_SNPRINTF; - - /* - * Optional extensions - */ -#if !defined(MBEDTLS_IOT_SPECIFIC) - if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) - { - ret = mbedtls_snprintf( p, n, "\r\n%sbasic constraints : CA=%s", prefix, - crt->ca_istrue ? "true" : "false" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( crt->max_pathlen > 0 ) - { - ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - } - - if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) - { - ret = mbedtls_snprintf( p, n, "\r\n%ssubject alt name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = x509_info_subject_alt_name( &p, &n, - &crt->subject_alt_names ) ) != 0 ) - return( ret ); - } - - if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) - { - ret = mbedtls_snprintf( p, n, "\r\n%scert. type : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) - return( ret ); - } - - if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) - { - ret = mbedtls_snprintf( p, n, "\r\n%skey usage : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) - return( ret ); - } - - if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) - { - ret = mbedtls_snprintf( p, n, "\r\n%sext key usage : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = x509_info_ext_key_usage( &p, &n, - &crt->ext_key_usage ) ) != 0 ) - return( ret ); - } -#endif - - ret = mbedtls_snprintf( p, n, "\r\n" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( (int) ( size - n ) ); -} - -struct x509_crt_verify_string { - int code; - const char *string; -}; - -static const struct x509_crt_verify_string x509_crt_verify_strings[] = { - { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, - { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, - { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, - { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, - { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, - { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, - { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, - { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, - { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, - { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, - { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, - { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, - { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, - { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, - { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, - { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, - { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, - { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, - { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, - { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, - { 0, NULL } -}; - -int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, - uint32_t flags ) -{ - int ret; - const struct x509_crt_verify_string *cur; - char *p = buf; - size_t n = size; - - for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) - { - if( ( flags & cur->code ) == 0 ) - continue; - - ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); - MBEDTLS_X509_SAFE_SNPRINTF; - flags ^= cur->code; - } - - if( flags != 0 ) - { - ret = mbedtls_snprintf( p, n, "%sUnknown reason " - "(this should not happen)\n", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - return( (int) ( size - n ) ); -} - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) -int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, - unsigned int usage ) -{ - unsigned int usage_must, usage_may; - unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY - | MBEDTLS_X509_KU_DECIPHER_ONLY; - - if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) - return( 0 ); - - usage_must = usage & ~may_mask; - - if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - usage_may = usage & may_mask; - - if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - return( 0 ); -} -#endif - -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) -int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, - const char *usage_oid, - size_t usage_len ) -{ - const mbedtls_x509_sequence *cur; - - /* Extension is not mandatory, absent means no restriction */ - if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) - return( 0 ); - - /* - * Look for the requested usage (or wildcard ANY) in our list - */ - for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) - { - const mbedtls_x509_buf *cur_oid = &cur->buf; - - if( cur_oid->len == usage_len && - memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) - { - return( 0 ); - } - - if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) - return( 0 ); - } - - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); -} -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ - -#if defined(MBEDTLS_X509_CRL_PARSE_C) -/* - * Return 1 if the certificate is revoked, or 0 otherwise. - */ -int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) -{ - const mbedtls_x509_crl_entry *cur = &crl->entry; - - while( cur != NULL && cur->serial.len != 0 ) - { - if( crt->serial.len == cur->serial.len && - memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) - { - if( mbedtls_x509_time_is_past( &cur->revocation_date ) ) - return( 1 ); - } - - cur = cur->next; - } - - return( 0 ); -} - -/* - * Check that the given certificate is not revoked according to the CRL. - * Skip validation is no CRL for the given CA is present. - */ -static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, - mbedtls_x509_crl *crl_list, - const mbedtls_x509_crt_profile *profile ) -{ - int flags = 0; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - - if( ca == NULL ) - return( flags ); - - while( crl_list != NULL ) - { - if( crl_list->version == 0 || - crl_list->issuer_raw.len != ca->subject_raw.len || - memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, - crl_list->issuer_raw.len ) != 0 ) - { - crl_list = crl_list->next; - continue; - } - - /* - * Check if the CA is configured to sign CRLs - */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) - { - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } -#endif - - /* - * Check if CRL is correctly signed by the trusted CA - */ - if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) - flags |= MBEDTLS_X509_BADCRL_BAD_MD; - - if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) - flags |= MBEDTLS_X509_BADCRL_BAD_PK; - - md_info = mbedtls_md_info_from_type( crl_list->sig_md ); - if( md_info == NULL ) - { - /* - * Cannot check 'unknown' hash - */ - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } - - mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); - - if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 ) - flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, - crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), - crl_list->sig.p, crl_list->sig.len ) != 0 ) - { - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } - - /* - * Check for validity of CRL (Do not drop out) - */ - if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) - flags |= MBEDTLS_X509_BADCRL_EXPIRED; - - if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) - flags |= MBEDTLS_X509_BADCRL_FUTURE; - - /* - * Check if certificate is revoked - */ - if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) - { - flags |= MBEDTLS_X509_BADCERT_REVOKED; - break; - } - - crl_list = crl_list->next; - } - - return( flags ); -} -#endif /* MBEDTLS_X509_CRL_PARSE_C */ - -/* - * Like memcmp, but case-insensitive and always returns -1 if different - */ -static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) -{ - size_t i; - unsigned char diff; - const unsigned char *n1 = s1, *n2 = s2; - - for( i = 0; i < len; i++ ) - { - diff = n1[i] ^ n2[i]; - - if( diff == 0 ) - continue; - - if( diff == 32 && - ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || - ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) - { - continue; - } - - return( -1 ); - } - - return( 0 ); -} - -/* - * Return 0 if name matches wildcard, -1 otherwise - */ -static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name ) -{ - size_t i; - size_t cn_idx = 0, cn_len = strlen( cn ); - - if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) - return( 0 ); - - for( i = 0; i < cn_len; ++i ) - { - if( cn[i] == '.' ) - { - cn_idx = i; - break; - } - } - - if( cn_idx == 0 ) - return( -1 ); - - if( cn_len - cn_idx == name->len - 1 && - x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) - { - return( 0 ); - } - - return( -1 ); -} - -/* - * Compare two X.509 strings, case-insensitive, and allowing for some encoding - * variations (but not all). - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) -{ - if( a->tag == b->tag && - a->len == b->len && - memcmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - a->len == b->len && - x509_memcasecmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - return( -1 ); -} - -/* - * Compare two X.509 Names (aka rdnSequence). - * - * See RFC 5280 section 7.1, though we don't implement the whole algorithm: - * we sometimes return unequal when the full algorithm would return equal, - * but never the other way. (In particular, we don't do Unicode normalisation - * or space folding.) - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) -{ - /* Avoid recursion, it might not be optimised by the compiler */ - while( a != NULL || b != NULL ) - { - if( a == NULL || b == NULL ) - return( -1 ); - - /* type */ - if( a->oid.tag != b->oid.tag || - a->oid.len != b->oid.len || - memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) - { - return( -1 ); - } - - /* value */ - if( x509_string_cmp( &a->val, &b->val ) != 0 ) - return( -1 ); - - /* structure of the list of sets */ - if( a->next_merged != b->next_merged ) - return( -1 ); - - a = a->next; - b = b->next; - } - - /* a == NULL == b */ - return( 0 ); -} - -/* - * Check if 'parent' is a suitable parent (signing CA) for 'child'. - * Return 0 if yes, -1 if not. - * - * top means parent is a locally-trusted certificate - * bottom means child is the end entity cert - */ -static int x509_crt_check_parent( const mbedtls_x509_crt *child, - const mbedtls_x509_crt *parent, - int top, int bottom ) -{ - int need_ca_bit; - - /* Parent must be the issuer */ - if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) - return( -1 ); - - /* Parent must have the basicConstraints CA bit set as a general rule */ - need_ca_bit = 1; - - /* Exception: v1/v2 certificates that are locally trusted. */ - if( top && parent->version < 3 ) - need_ca_bit = 0; - - /* Exception: self-signed end-entity certs that are locally trusted. */ - if( top && bottom && - child->raw.len == parent->raw.len && - memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) - { - need_ca_bit = 0; - } - - if( need_ca_bit && ! parent->ca_istrue ) - return( -1 ); - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if( need_ca_bit && - mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) - { - return( -1 ); - } -#endif - - return( 0 ); -} - -static int x509_crt_verify_top( - mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - int path_cnt, int self_cnt, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - int ret; - uint32_t ca_flags = 0; - int check_path_cnt; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - mbedtls_x509_crt *future_past_ca = NULL; - - if( mbedtls_x509_time_is_past( &child->valid_to ) ) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - if( mbedtls_x509_time_is_future( &child->valid_from ) ) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - /* - * Child is the top of the chain. Check against the trust_ca list. - */ - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - - md_info = mbedtls_md_info_from_type( child->sig_md ); - if( md_info == NULL ) - { - /* - * Cannot check 'unknown', no need to try any CA - */ - trust_ca = NULL; - } - else - mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); - - for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) - { - if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) - continue; - - check_path_cnt = path_cnt + 1; - - /* - * Reduce check_path_cnt to check against if top of the chain is - * the same as the trusted CA - */ - if( child->subject_raw.len == trust_ca->subject_raw.len && - memcmp( child->subject_raw.p, trust_ca->subject_raw.p, - child->issuer_raw.len ) == 0 ) - { - check_path_cnt--; - } - - /* Self signed certificates do not count towards the limit */ - if( trust_ca->max_pathlen > 0 && - trust_ca->max_pathlen < check_path_cnt - self_cnt ) - { - continue; - } - - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) - { - continue; - } - - if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) || - mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) - { - if ( future_past_ca == NULL ) - future_past_ca = trust_ca; - - continue; - } - - break; - } - - if( trust_ca != NULL || ( trust_ca = future_past_ca ) != NULL ) - { - /* - * Top of chain is signed by a trusted CA - */ - *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; - - if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - } - - /* - * If top of chain is not the same as the trusted CA send a verify request - * to the callback for any issues with validity and CRL presence for the - * trusted CA certificate. - */ - if( trust_ca != NULL && - ( child->subject_raw.len != trust_ca->subject_raw.len || - memcmp( child->subject_raw.p, trust_ca->subject_raw.p, - child->issuer_raw.len ) != 0 ) ) - { -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the chain's top crt */ - *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); -#else - ((void) ca_crl); -#endif - - if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ) - ca_flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) - ca_flags |= MBEDTLS_X509_BADCERT_FUTURE; - - if( NULL != f_vrfy ) - { - if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, - &ca_flags ) ) != 0 ) - { - return( ret ); - } - } - } - - /* Call callback on top cert */ - if( NULL != f_vrfy ) - { - if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) - return( ret ); - } - - *flags |= ca_flags; - - return( 0 ); -} - -static int x509_crt_verify_child( - mbedtls_x509_crt *child, mbedtls_x509_crt *parent, - mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - int path_cnt, int self_cnt, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - int ret; - uint32_t parent_flags = 0; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - mbedtls_x509_crt *grandparent; - const mbedtls_md_info_t *md_info; - - /* Counting intermediate self signed certificates */ - if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) - self_cnt++; - - /* path_cnt is 0 for the first intermediate CA */ - if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) - { - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); - } - - if( mbedtls_x509_time_is_past( &child->valid_to ) ) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if( mbedtls_x509_time_is_future( &child->valid_from ) ) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - - if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - - if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - md_info = mbedtls_md_info_from_type( child->sig_md ); - if( md_info == NULL ) - { - /* - * Cannot check 'unknown' hash - */ - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - } - else - { - mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); - - if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) - { - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - } - } - -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the given crt */ - *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile ); -#endif - - /* Look for a grandparent in trusted CAs */ - for( grandparent = trust_ca; - grandparent != NULL; - grandparent = grandparent->next ) - { - if( x509_crt_check_parent( parent, grandparent, - 0, path_cnt == 0 ) == 0 ) - break; - } - - if( grandparent != NULL ) - { - ret = x509_crt_verify_top( parent, grandparent, ca_crl, profile, - path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - /* Look for a grandparent upwards the chain */ - for( grandparent = parent->next; - grandparent != NULL; - grandparent = grandparent->next ) - { - /* +2 because the current step is not yet accounted for - * and because max_pathlen is one higher than it should be. - * Also self signed certificates do not count to the limit. */ - if( grandparent->max_pathlen > 0 && - grandparent->max_pathlen < 2 + path_cnt - self_cnt ) - { - continue; - } - - if( x509_crt_check_parent( parent, grandparent, - 0, path_cnt == 0 ) == 0 ) - break; - } - - /* Is our parent part of the chain or at the top? */ - if( grandparent != NULL ) - { - ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, - profile, path_cnt + 1, self_cnt, &parent_flags, - f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, - path_cnt + 1, self_cnt, &parent_flags, - f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - } - - /* child is verified to be a child of the parent, call verify callback */ - if( NULL != f_vrfy ) - if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) - return( ret ); - - *flags |= parent_flags; - - return( 0 ); -} - -/* - * Verify the certificate validity - */ -int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, - &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); -} - - -/* - * Verify the certificate validity, with profile - */ -int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - int ret; - int pathlen = 0, selfsigned = 0; - mbedtls_x509_crt *parent; - size_t cn_len; - mbedtls_x509_name *name; - mbedtls_x509_sequence *cur = NULL; - mbedtls_pk_type_t pk_type; - - if( profile == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - *flags = 0; - - if( cn != NULL ) - { - name = &crt->subject; - cn_len = strlen( cn ); - - if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) - { - cur = &crt->subject_alt_names; - - while( cur != NULL ) - { - if( cur->buf.len == cn_len && - x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 ) - break; - - if( cur->buf.len > 2 && - memcmp( cur->buf.p, "*.", 2 ) == 0 && - x509_check_wildcard( cn, &cur->buf ) == 0 ) - { - break; - } - - cur = cur->next; - } - - if( cur == NULL ) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - else - { - while( name != NULL ) - { - if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 ) - { - if( name->val.len == cn_len && - x509_memcasecmp( name->val.p, cn, cn_len ) == 0 ) - break; - - if( name->val.len > 2 && - memcmp( name->val.p, "*.", 2 ) == 0 && - x509_check_wildcard( cn, &name->val ) == 0 ) - break; - } - - name = name->next; - } - - if( name == NULL ) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - } - - /* Check the type and size of the key */ - pk_type = mbedtls_pk_get_type( &crt->pk ); - - if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - /* Look for a parent in trusted CAs */ - for( parent = trust_ca; parent != NULL; parent = parent->next ) - { - if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) - break; - } - - if( parent != NULL ) - { - ret = x509_crt_verify_top( crt, parent, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - /* Look for a parent upwards the chain */ - for( parent = crt->next; parent != NULL; parent = parent->next ) - if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) - break; - - /* Are we part of the chain or at the top? */ - if( parent != NULL ) - { - ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - } - - if( *flags != 0 ) { - return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); - } - return( 0 ); -} - -/* - * Initialize a certificate chain - */ -void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) -{ - memset( crt, 0, sizeof(mbedtls_x509_crt) ); -} - -/* - * Unallocate all certificate data - */ -void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) -{ - mbedtls_x509_crt *cert_cur = crt; - mbedtls_x509_crt *cert_prv; - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - mbedtls_x509_sequence *seq_cur; - mbedtls_x509_sequence *seq_prv; - - if( crt == NULL ) - return; - - do - { - mbedtls_pk_free( &cert_cur->pk ); - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - mbedtls_free( cert_cur->sig_opts ); -#endif - - name_cur = cert_cur->issuer.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); - mbedtls_free( name_prv ); - } - - name_cur = cert_cur->subject.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); - mbedtls_free( name_prv ); - } - - seq_cur = cert_cur->ext_key_usage.next; - while( seq_cur != NULL ) - { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); - mbedtls_free( seq_prv ); - } - - seq_cur = cert_cur->subject_alt_names.next; - while( seq_cur != NULL ) - { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); - mbedtls_free( seq_prv ); - } - - if( cert_cur->raw.p != NULL ) - { - mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len ); - mbedtls_free( cert_cur->raw.p ); - } - - cert_cur = cert_cur->next; - } - while( cert_cur != NULL ); - - cert_cur = crt; - do - { - cert_prv = cert_cur; - cert_cur = cert_cur->next; - - mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); - if( cert_prv != crt ) - mbedtls_free( cert_prv ); - } - while( cert_cur != NULL ); -} - -#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/components/security/mbedtls/src/x509_csr.c b/components/security/mbedtls/src/x509_csr.c deleted file mode 100644 index a34539e3..00000000 --- a/components/security/mbedtls/src/x509_csr.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * X.509 Certificate Signing Request (CSR) parsing - * - * 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) - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CSR_PARSE_C) - -#include "mbedtls/x509_csr.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_snprintf snprintf -#endif - -#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) -#include -#endif - -/* 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; -} - -/* - * Version ::= INTEGER { v1(0) } - */ -static int x509_csr_get_version( unsigned char **p, - const unsigned char *end, - int *ver ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - *ver = 0; - return( 0 ); - } - - return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); - } - - return( 0 ); -} - -/* - * Parse a CSR in DER format - */ -int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, - const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - mbedtls_x509_buf sig_params; - - memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); - - /* - * Check for valid input - */ - if( csr == NULL || buf == NULL || buflen == 0 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - mbedtls_x509_csr_init( csr ); - - /* - * first copy the raw DER data - */ - p = mbedtls_calloc( 1, len = buflen ); - - if( p == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - csr->raw.p = p; - csr->raw.len = len; - end = p + len; - - /* - * CertificationRequest ::= SEQUENCE { - * certificationRequestInfo CertificationRequestInfo, - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT ); - } - - if( len != (size_t) ( end - p ) ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - /* - * CertificationRequestInfo ::= SEQUENCE { - */ - csr->cri.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - end = p + len; - csr->cri.len = end - csr->cri.p; - - /* - * Version ::= INTEGER { v1(0) } - */ - if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - csr->version++; - - if( csr->version != 1 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); - } - - /* - * subject Name - */ - csr->subject_raw.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - csr->subject_raw.len = p - csr->subject_raw.p; - - /* - * subjectPKInfo SubjectPublicKeyInfo - */ - if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - /* - * attributes [0] Attributes - * - * The list of possible attributes is open-ended, though RFC 2985 - * (PKCS#9) defines a few in section 5.4. We currently don't support any, - * so we just ignore them. This is a safe thing to do as the worst thing - * that could happen is that we issue a certificate that does not match - * the requester's expectations - this cannot cause a violation of our - * signature policies. - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - p += len; - - end = csr->raw.p + csr->raw.len; - - /* - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING - */ - if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, - &csr->sig_md, &csr->sig_pk, - &csr->sig_opts ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); - } - - if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - if( p != end ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - return( 0 ); -} - -/* - * Parse a CSR, allowing for PEM or raw DER encoding - */ -int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) -{ -#if defined(MBEDTLS_PEM_PARSE_C) - int ret; - size_t use_len; - mbedtls_pem_context pem; -#endif - - /* - * Check for valid input - */ - if( csr == NULL || buf == NULL || buflen == 0 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init( &pem ); - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( buf[buflen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN CERTIFICATE REQUEST-----", - "-----END CERTIFICATE REQUEST-----", - buf, NULL, 0, &use_len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded, parse the result - */ - if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) - return( ret ); - - mbedtls_pem_free( &pem ); - return( 0 ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } - else -#endif /* MBEDTLS_PEM_PARSE_C */ - return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load a CSR into the structure - */ -int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_x509_csr_parse( csr, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -#define BEFORE_COLON 14 -#define BC "14" -/* - * Return an informational string about the CSR. - */ -int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_csr *csr ) -{ - int ret; - size_t n; - char *p; - char key_size_str[BEFORE_COLON]; - - p = buf; - n = size; - - ret = mbedtls_snprintf( p, n, "%sCSR version : %d", - prefix, csr->version ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); - MBEDTLS_X509_SAFE_SNPRINTF; - -#if !defined(MBEDTLS_IOT_SPECIFIC) - ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, - csr->sig_opts ); - MBEDTLS_X509_SAFE_SNPRINTF; -#endif /* MBEDTLS_IOT_SPECIFIC */ - - if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, - mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) - { - return( ret ); - } - - ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, - (int) mbedtls_pk_get_bitlen( &csr->pk ) ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( (int) ( size - n ) ); -} - -/* - * Initialize a CSR - */ -void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) -{ - memset( csr, 0, sizeof(mbedtls_x509_csr) ); -} - -/* - * Unallocate all CSR data - */ -void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) -{ - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - - if( csr == NULL ) - return; - - mbedtls_pk_free( &csr->pk ); - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - mbedtls_free( csr->sig_opts ); -#endif - - name_cur = csr->subject.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); - mbedtls_free( name_prv ); - } - - if( csr->raw.p != NULL ) - { - mbedtls_zeroize( csr->raw.p, csr->raw.len ); - mbedtls_free( csr->raw.p ); - } - - mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) ); -} - -#endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/components/security/mbedtls/src/x509write_crt.c b/components/security/mbedtls/src/x509write_crt.c deleted file mode 100644 index d1d9a22a..00000000 --- a/components/security/mbedtls/src/x509write_crt.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * X.509 certificate writing - * - * 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) - */ -/* - * References: - * - certificates: RFC 5280, updated by RFC 6818 - * - CSRs: PKCS#10 v1.7 aka RFC 2986 - * - attributes: PKCS#9 v2.0 aka RFC 2985 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CRT_WRITE_C) - -#include "mbedtls/x509_crt.h" -#include "mbedtls/oid.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/sha1.h" - -#include - -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif /* MBEDTLS_PEM_WRITE_C */ - -/* 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; -} - -void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) -{ - memset( ctx, 0, sizeof(mbedtls_x509write_cert) ); - - mbedtls_mpi_init( &ctx->serial ); - ctx->version = MBEDTLS_X509_CRT_VERSION_3; -} - -void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) -{ - mbedtls_mpi_free( &ctx->serial ); - - mbedtls_asn1_free_named_data_list( &ctx->subject ); - mbedtls_asn1_free_named_data_list( &ctx->issuer ); - mbedtls_asn1_free_named_data_list( &ctx->extensions ); - - mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_cert) ); -} - -void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) -{ - ctx->version = version; -} - -void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ) -{ - ctx->md_alg = md_alg; -} - -void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) -{ - ctx->subject_key = key; -} - -void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) -{ - ctx->issuer_key = key; -} - -int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, - const char *subject_name ) -{ - return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); -} - -int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, - const char *issuer_name ) -{ - return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); -} - -int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ) -{ - int ret; - - if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, - const char *not_after ) -{ - if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || - strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) - { - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - } - strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); - strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); - ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; - ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; - - return( 0 ); -} - -int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, - const char *oid, size_t oid_len, - int critical, - const unsigned char *val, size_t val_len ) -{ - return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, - critical, val, val_len ); -} - -int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, - int is_ca, int max_pathlen ) -{ - int ret; - unsigned char buf[9]; - unsigned char *c = buf + sizeof(buf); - size_t len = 0; - - memset( buf, 0, sizeof(buf) ); - - if( is_ca && max_pathlen > 127 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - if( is_ca ) - { - if( max_pathlen >= 0 ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) ); - } - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, - MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), - 0, buf + sizeof(buf) - len, len ); -} - -#if defined(MBEDTLS_SHA1_C) -int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) -{ - int ret; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ - unsigned char *c = buf + sizeof(buf); - size_t len = 0; - - memset( buf, 0, sizeof(buf) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); - - mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); - c = buf + sizeof(buf) - 20; - len = 20; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); - - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, - MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), - 0, buf + sizeof(buf) - len, len ); -} - -int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) -{ - int ret; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ - unsigned char *c = buf + sizeof(buf); - size_t len = 0; - - memset( buf, 0, sizeof(buf) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); - - mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); - c = buf + sizeof(buf) - 20; - len = 20; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, - MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), - 0, buf + sizeof(buf) - len, len ); -} -#endif /* MBEDTLS_SHA1_C */ - -int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, - unsigned int key_usage ) -{ - unsigned char buf[4], ku; - unsigned char *c; - int ret; - - /* We currently only support 7 bits, from 0x80 to 0x02 */ - if( ( key_usage & ~0xfe ) != 0 ) - return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); - - c = buf + 4; - ku = (unsigned char) key_usage; - - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) - return( ret ); - - ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), - 1, buf, 4 ); - if( ret != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, - unsigned char ns_cert_type ) -{ - unsigned char buf[4]; - unsigned char *c; - int ret; - - c = buf + 4; - - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) - return( ret ); - - ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), - 0, buf, 4 ); - if( ret != 0 ) - return( ret ); - - return( 0 ); -} - -static int x509_write_time( unsigned char **p, unsigned char *start, - const char *time, size_t size ) -{ - int ret; - size_t len = 0; - - /* - * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) - */ - if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) time + 2, - size - 2 ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); - } - else - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) time, - size ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); - } - - return( (int) len ); -} - -int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - const char *sig_oid; - size_t sig_oid_len = 0; - unsigned char *c, *c2; - unsigned char hash[64]; - unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; - unsigned char tmp_buf[2048]; - size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; - size_t len = 0; - mbedtls_pk_type_t pk_alg; - - /* - * Prepare data to be signed in tmp_buf - */ - c = tmp_buf + sizeof( tmp_buf ); - - /* Signature algorithm needed in TBS, and later for actual signature */ - pk_alg = mbedtls_pk_get_type( ctx->issuer_key ); - if( pk_alg == MBEDTLS_PK_ECKEY ) - pk_alg = MBEDTLS_PK_ECDSA; - - if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, - &sig_oid, &sig_oid_len ) ) != 0 ) - { - return( ret ); - } - - /* - * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); - - /* - * SubjectPublicKeyInfo - */ - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, - tmp_buf, c - tmp_buf ) ); - c -= pub_len; - len += pub_len; - - /* - * Subject ::= Name - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - */ - sub_len = 0; - - MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, - MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); - - MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, - MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); - - len += sub_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - /* - * Issuer ::= Name - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); - - /* - * Signature ::= AlgorithmIdentifier - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, - sig_oid, strlen( sig_oid ), 0 ) ); - - /* - * Serial ::= INTEGER - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ - sub_len = 0; - MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); - len += sub_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - /* - * Make signature - */ - mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); - - if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, - f_rng, p_rng ) ) != 0 ) - { - return( ret ); - } - - /* - * Write data to output buffer - */ - c2 = buf + size; - MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, - sig_oid, sig_oid_len, sig, sig_len ) ); - - if( len > (size_t)( c2 - buf ) ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - c2 -= len; - memcpy( c2, c, len ); - - len += sig_and_oid_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" -#define PEM_END_CRT "-----END CERTIFICATE-----\n" - -#if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char output_buf[4096]; - size_t olen = 0; - - if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), - f_rng, p_rng ) ) < 0 ) - { - return( ret ); - } - - if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_X509_CRT_WRITE_C */ diff --git a/components/security/mbedtls/src/x509write_csr.c b/components/security/mbedtls/src/x509write_csr.c deleted file mode 100644 index 8fd856b2..00000000 --- a/components/security/mbedtls/src/x509write_csr.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * X.509 Certificate Signing Request writing - * - * 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) - */ -/* - * References: - * - CSRs: PKCS#10 v1.7 aka RFC 2986 - * - attributes: PKCS#9 v2.0 aka RFC 2985 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CSR_WRITE_C) - -#include "mbedtls/x509_csr.h" -#include "mbedtls/oid.h" -#include "mbedtls/asn1write.h" - -#include -#include - -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -/* 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; -} - -void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) -{ - memset( ctx, 0, sizeof(mbedtls_x509write_csr) ); -} - -void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) -{ - mbedtls_asn1_free_named_data_list( &ctx->subject ); - mbedtls_asn1_free_named_data_list( &ctx->extensions ); - - mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_csr) ); -} - -void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) -{ - ctx->md_alg = md_alg; -} - -void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) -{ - ctx->key = key; -} - -int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, - const char *subject_name ) -{ - return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); -} - -int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, - const char *oid, size_t oid_len, - const unsigned char *val, size_t val_len ) -{ - return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, - 0, val, val_len ); -} - -int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) -{ - unsigned char buf[4]; - unsigned char *c; - int ret; - - c = buf + 4; - - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) - return( ret ); - - ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), - buf, 4 ); - if( ret != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, - unsigned char ns_cert_type ) -{ - unsigned char buf[4]; - unsigned char *c; - int ret; - - c = buf + 4; - - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) - return( ret ); - - ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), - buf, 4 ); - if( ret != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - const char *sig_oid; - size_t sig_oid_len = 0; - unsigned char *c, *c2; - unsigned char hash[64]; - unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; - unsigned char tmp_buf[2048]; - size_t pub_len = 0, sig_and_oid_len = 0, sig_len; - size_t len = 0; - mbedtls_pk_type_t pk_alg; - - /* - * Prepare data to be signed in tmp_buf - */ - c = tmp_buf + sizeof( tmp_buf ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); - - if( len ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SET ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, - MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); - - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, - tmp_buf, c - tmp_buf ) ); - c -= pub_len; - len += pub_len; - - /* - * Subject ::= Name - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - /* - * Prepare signature - */ - mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); - - pk_alg = mbedtls_pk_get_type( ctx->key ); - if( pk_alg == MBEDTLS_PK_ECKEY ) - pk_alg = MBEDTLS_PK_ECDSA; - - if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, - f_rng, p_rng ) ) != 0 || - ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, - &sig_oid, &sig_oid_len ) ) != 0 ) - { - return( ret ); - } - - /* - * Write data to output buffer - */ - c2 = buf + size; - MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, - sig_oid, sig_oid_len, sig, sig_len ) ); - - if( len > (size_t)( c2 - buf ) ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - c2 -= len; - memcpy( c2, c, len ); - - len += sig_and_oid_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" -#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" - -#if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char output_buf[4096]; - size_t olen = 0; - - if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), - f_rng, p_rng ) ) < 0 ) - { - return( ret ); - } - - if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_X509_CSR_WRITE_C */ diff --git a/components/security/mbedtls/src/xtea.c b/components/security/mbedtls/src/xtea.c deleted file mode 100644 index fe0a3509..00000000 --- a/components/security/mbedtls/src/xtea.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * An 32-bit implementation of the XTEA algorithm - * - * 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_XTEA_C) - -#include "mbedtls/xtea.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_XTEA_ALT) - -/* 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; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -void mbedtls_xtea_init( mbedtls_xtea_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_xtea_context ) ); -} - -void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); -} - -/* - * XTEA key schedule - */ -void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ) -{ - int i; - - memset( ctx, 0, sizeof(mbedtls_xtea_context) ); - - for( i = 0; i < 4; i++ ) - { - GET_UINT32_BE( ctx->k[i], key, i << 2 ); - } -} - -/* - * XTEA encrypt function - */ -int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode, - const unsigned char input[8], unsigned char output[8]) -{ - uint32_t *k, v0, v1, i; - - k = ctx->k; - - GET_UINT32_BE( v0, input, 0 ); - GET_UINT32_BE( v1, input, 4 ); - - if( mode == MBEDTLS_XTEA_ENCRYPT ) - { - uint32_t sum = 0, delta = 0x9E3779B9; - - for( i = 0; i < 32; i++ ) - { - v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - sum += delta; - v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); - } - } - else /* MBEDTLS_XTEA_DECRYPT */ - { - uint32_t delta = 0x9E3779B9, sum = delta * 32; - - for( i = 0; i < 32; i++ ) - { - v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); - sum -= delta; - v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - } - } - - PUT_UINT32_BE( v0, output, 0 ); - PUT_UINT32_BE( v1, output, 4 ); - - return( 0 ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * XTEA-CBC buffer encryption/decryption - */ -int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length, - unsigned char iv[8], const unsigned char *input, - unsigned char *output) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_XTEA_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - mbedtls_xtea_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_xtea_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* !MBEDTLS_XTEA_ALT */ - -#if defined(MBEDTLS_SELF_TEST) - -/* - * XTEA tests vectors (non-official) - */ - -static const unsigned char xtea_test_key[6][16] = -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char xtea_test_pt[6][8] = -{ - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } -}; - -static const unsigned char xtea_test_ct[6][8] = -{ - { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, - { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, - { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } -}; - -/* - * Checkup routine - */ -int mbedtls_xtea_self_test( int verbose ) -{ - int i, ret = 0; - unsigned char buf[8]; - mbedtls_xtea_context ctx; - - mbedtls_xtea_init( &ctx ); - for( i = 0; i < 6; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " XTEA test #%d: ", i + 1 ); - - memcpy( buf, xtea_test_pt[i], 8 ); - - mbedtls_xtea_setup( &ctx, xtea_test_key[i] ); - mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf ); - - if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_xtea_free( &ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_XTEA_C */ diff --git a/components/security/mbedtls/version b/components/security/mbedtls/version deleted file mode 100644 index cc4f39f6..00000000 --- a/components/security/mbedtls/version +++ /dev/null @@ -1,2 +0,0 @@ -Get From Alios-Things, commit: -1ee61e42883a518e9d9481447b6bccc1b93985ba