wolfSSL / wolfssl

The wolfSSL library is a small, fast, portable implementation of TLS/SSL for embedded devices to the cloud. wolfSSL supports up to TLS 1.3 and DTLS 1.3!
https://www.wolfssl.com
GNU General Public License v2.0
2.34k stars 830 forks source link

Support WICED Studio #1266

Closed master-q closed 6 years ago

master-q commented 6 years ago

The progress code is found at https://gitlab.com/masterq/WICED-Studio-6.0-wolfSSL. (I can't locate it at GitHub, because the object size is limited.)

TODO:

master-q commented 6 years ago

The mbedtls is located at /home/User/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/mbedtls_open. Then, we can pick up number of calling mbedtls API as following:

$ pwd
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi
$ grep mbedtls_ -r | grep -v BESL/mbedtls_open | grep -v "^Binary file" | wc -l
379
master-q commented 6 years ago

The API callings are categorized into following:

master-q commented 6 years ago

WICED/security/BESL/host/WICED/wiced_supplicant.c library is called by WIFI_COMMANDS macro:

#define WIFI_COMMANDS \
    ALL_COMMANDS_ENTERPRISE_SECURITY_COMMANDS \
    WIFI_COMMANDS_LIMITED_SET \
// --snip--
    { (char*) "test_join",                          test_join,                          2, NULL, NULL, (char*) "<ssid> <open|wep|wpa_aes|wpa_tkip|wpa2|wpa2_tkip> [key] [ip netmask gateway] <iterations>"ESCAPE_SPACE_PROMPT, (char*) "Test joining an AP. DHCP assumed if no IP address provided"}, \

And above commands is called by following applications:

master-q commented 6 years ago

Planed. But there are no good test for WICED/* library. I believe apps/test/console is a choice, but I have no concrete command sequences for better coverage of testing...

master-q commented 6 years ago

Choose 1st build target:

$ pwd
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi
$ ./make.sh test.console-CYW943907AEVAL1F-FreeRTOS-LwIP
$ find build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/ -name "*.o" | grep mbedtls | head
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/version_features.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/dhm.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/pk.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/ecdh.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/pkparse.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/havege.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/ssl_ticket.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/x509_csr.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/entropy.o
build/test.console-CYW943907AEVAL1F-FreeRTOS-LwIP/Modules/WICED/security/BESL/mbedtls_open/library/cmac.o
master-q commented 6 years ago

@cconlon Do you have some manual to map mbed TLS API into wolfSSL? If no, may I create it at GItHub Wiki?

master-q commented 6 years ago

Added wolfSSL as COMPONENTS which can be built on WICED-Studio-6.0.

But I didn't choose the correct compile options which are following:

After port wolfcrypt/test/test.c onto WICED-Studio-6.0, I should review the options.

master-q commented 6 years ago

Explained how to build wolfSSL on WICED-Studio-6.0:

master-q commented 6 years ago

Get following error, while build test.c:

Making test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP.elf
build/test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP/libraries/wolfSSL.a(test.o): In function `wolfcrypt_test':
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/test/test.c:415: undefined reference to `CheckRunTimeSettings'
build/test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP/libraries/wolfSSL.a(rsa.o): In function `wc_InitRsaKey_ex':
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:247: undefined reference to `mp_init_multi'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:251: undefined reference to `mp_init_multi'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:253: undefined reference to `mp_clear'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:254: undefined reference to `mp_clear'
build/test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP/libraries/wolfSSL.a(rsa.o): In function `wc_FreeRsaKey':
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:362: undefined reference to `mp_forcezero'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:363: undefined reference to `mp_forcezero'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:364: undefined reference to `mp_forcezero'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:365: undefined reference to `mp_forcezero'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:366: undefined reference to `mp_forcezero'
build/test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP/libraries/wolfSSL.a(rsa.o):/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:367: more undefined references to `mp_forcezero' follow
build/test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP/libraries/wolfSSL.a(rsa.o): In function `wc_FreeRsaKey':
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:370: undefined reference to `mp_clear'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:371: undefined reference to `mp_clear'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:372: undefined reference to `mp_clear'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:373: undefined reference to `mp_clear'
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi/WICED/security/BESL/wolfssl/IDE/WICED-Studio/../../wolfcrypt/src/rsa.c:374: undefined reference to `mp_clear'
--snip--
master-q commented 6 years ago

Get following error, while build test.c:

Fix them adding -DUSE_FAST_MATH:

$ ./make_test_wolfssl_test_freertos.sh
--snip--
----------------------------------|---------|---------|
                                  |         |  Static |
              Module              |  Flash  |   RAM   |
----------------------------------+---------+---------|
App                               |       0 |     104 |
crc                               |       0 |    1060 |
FreeRTOS                          |       0 |    6625 |
Interrupt Vectors                 |       0 |     288 |
libc                              |       0 |   30818 |
LwIP                              |       0 |   39023 |
Networking                        |       0 |    1483 |
NVRam                             |       0 |    2210 |
Other                             |       0 |  154751 |
Packet Buffers                    |       0 |  110892 |
platform                          |       0 |     478 |
RAM Initialisation                |      32 |       0 |
resources                         |       0 |      32 |
Ring_Buffer                       |       0 |     140 |
Startup Stack & Link Script fill  |       0 |     275 |
WICED                             |       0 |    4035 |
Wiced_RO_FS                       |       0 |     570 |
WWD                               |       0 |     956 |
----------------------------------+---------+---------|
TOTAL (bytes)                     |       0 |  353740 |
----------------------------------|---------|---------|
--snip--
$ nm build/test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP/binary/test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP.elf | grep wolfcrypt_test
004ad350 T wolfcrypt_test
master-q commented 6 years ago

Used GLOBAL_DEFINES to remove duplicated compile options:

https://github.com/master-q/wolfssl/commit/3d42f00642ee86a0da74d77e17fdfaca372582ee

master-q commented 6 years ago

Just clean up compile options:

Pushed it. https://github.com/master-q/wolfssl/commit/5a18f6d4330b787e397e6a4b3c3ae70e00f8f92b

master-q commented 6 years ago

The mbed TLS's API is used from following functions in WICED-Studio-6.0 middleware:

master-q commented 6 years ago

Above function used by following applications:

master-q commented 6 years ago

Before translate mbed TLS API onto wolfSSL, I think I should read https://tls.mbed.org/high-level-design.

cconlon commented 6 years ago

Thanks for the update

master-q commented 6 years ago

Next, I should read https://tls.mbed.org/kb/how-to/mbedtls-tutorial.

master-q commented 6 years ago

Build and run following test application:

https://gitlab.com/masterq/WICED-Studio-6.0-wolfSSL/blob/master/43xxx_Wi-Fi/apps/test/wolfssl_test/wolfssl_test.c

$ pwd
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi
$ ./make.sh test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP download run
$ picocom -b 115200 /dev/ttyUSB1
Crypt Test
error    test passed!
base64   test passed!
base64   test passed!
MD5      test passed!
MD4      test passed!
SHA      test passed!
SHA-224  test passed!
SHA-256  test passed!
SHA-384  test passed!
SHA-512  test passed!
SHA-3    test passed!
Hash     test passed!
HMAC-MD5 test passed!
HMAC-SHA test passed!
HMAC-SHA224 test passed!
HMAC-SHA256 test passed!
HMAC-SHA384 test passed!
HMAC-SHA512 test passed!
Chacha   test passed!
POLY1305 test passed!
ChaCha20-Poly1305 AEAD test passed!
DES      test passed!
DES3     test passed!
AES      test passed!
AES192   test passed!
AES256   test passed!
RANDOM   test failed!
 error = -5004
Crypt Test: Return code -1

Why the RANDOM test failed?

master-q commented 6 years ago

Error code -5004 means random_rng_test() returns a non-zero value.

master-q commented 6 years ago

There are many int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz). Which should I use?

master-q commented 6 years ago

My build option uses /dev/urandom, which is not found at WICED platform of course. Let's search where mbed TLS in WICED gets entropy from.

master-q commented 6 years ago

Umm... Is it O.K. for production? > Cypress

// WICED/security/BESL/mbedtls_open/include/mbedtls/config.h
--snip--
#define MBEDTLS_ENTROPY_MAX_SOURCES 2

/* extra added by Cypress */
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_TEST_NULL_ENTROPY
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
--snip--
// WICED/security/BESL/mbedtls_open/library/entropy.c
--snip--
#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
master-q commented 6 years ago

I found an test application creating random numbers with WICED API:

$ ./make.sh test.entropy-CYW943907AEVAL1F-FreeRTOS-LwIP download run
$ picocom -b 115200 /dev/ttyUSB1
Starting WICED vWiced_006.000.001.0005
Platform CYW943907AEVAL1F initialised
Started FreeRTOS v9.0.0
Initialising LwIP v2.0.2
DHCP CLIENT hostname WICED IP
WLAN MAC Address : A4:08:EA:D9:BC:A8
WLAN Firmware    : wl0: Oct 23 2017 03:40:42 version 7.15.168.101 (r674438) FWID 01-13cae12
WLAN CLM         : API: 12.2 Data: 9.10.74 Compiler: 1.31.3 ClmImport: 1.36.3 Creation: 2017-10-23 03:36:41 
-------
Default PRNG:
--------

RANDOM TEST (64 bytes)
Entropy = 5.812500 bits per byte.

Optimum compression would reduce the size
of this 64 byte file by 27 percent.

Chi square distribution for 64 samples is 240.00, and randomly
would exceed this value less than 0.01 percent of the times.

Arithmetic mean value of data bytes is 146.5312 (127.5 = random).
Monte Carlo value for Pi is 2.400000000 (error 23.61 percent).
Serial correlation coefficient is 0.083711 (totally uncorrelated = 0.0).
Run succeeded

-------
Secure PRNG:
--------

RANDOM TEST (64 bytes)
Entropy = 5.706955 bits per byte.

Optimum compression would reduce the size
of this 64 byte file by 28 percent.

Chi square distribution for 64 samples is 272.00, and randomly
would exceed this value less than 0.01 percent of the times.

Arithmetic mean value of data bytes is 125.8594 (127.5 = random).
Monte Carlo value for Pi is 3.200000000 (error 1.86 percent).
Serial correlation coefficient is 0.045149 (totally uncorrelated = 0.0).
Run succeeded

Done - press reset on board to continue!
master-q commented 6 years ago

There is wiced_result_t wiced_crypto_get_random( void* buffer, uint16_t buffer_length ) to get list of random numbers. The API has two mode. One is regular PRNG. The other is secure PRNG which needs around 6K of heap.

master-q commented 6 years ago

Added the wiced_crypto_get_random() function using WICED API.

But following errors occur. Their sequence:

  1. Boot WICED platform.
  2. Run test.
  3. The base64 test failed.
  4. Wait 3 seconds.
  5. Run test.
  6. Reboot WICED platform after RANDOM test.
Starting WICED vWiced_006.000.001.0005
Platform CYW943907AEVAL1F initialised
Started FreeRTOS v9.0.0
Initialising LwIP v2.0.2
DHCP CLIENT hostname WICED IP
WLAN MAC Address : A4:08:EA:D9:BC:A8
WLAN Firmware    : wl0: Oct 23 2017 03:40:42 version 7.15.168.101 (r674438) FWID 01-13cae12
WLAN CLM         : API: 12.2 Data: 9.10.74 Compiler: 1.31.3 ClmImport: 1.36.3 Creation: 2017-10-23 03:36:41 

Crypt Test
error    test passed!
base64   test passed!
RTC/Time not set!
base64   test failed!
 error = -1303
Crypt Test: Return code -1
Sleep 3 seconds to restart...

Crypt Test
error    test passed!
base64   test passed!
base64   test passed!
MD5      test passed!
MD4      test passed!
SHA      test passed!
SHA-224  test passed!
SHA-256  test passed!
SHA-384  test passed!
SHA-512  test passed!
SHA-3    test passed!
Hash     test passed!
HMAC-MD5 test passed!
HMAC-SHA test passed!
HMAC-SHA224 test passed!
HMAC-SHA256 test passed!
HMAC-SHA384 test passed!
HMAC-SHA512 test passed!
Chacha   test passed!
POLY1305 test passed!
ChaCha20-Poly1305 AEAD test passed!
DES      test passed!
DES3     test passed!
AES      test passed!
AES192   test passed!
AES256   test passed!
RANDOM   test passed!

Starting WICED vWiced_006.000.001.0005
Platform CYW943907AEVAL1F initialised
Started FreeRTOS v9.0.0
Initialising LwIP v2.0.2
DHCP CLIENT hostname WICED IP
WLAN MAC Address : A4:08:EA:D9:BC:A8
WLAN Firmware    : wl0: Oct 23 2017 03:40:42 version 7.15.168.101 (r674438) FWID 01-13cae12
WLAN CLM         : API: 12.2 Data: 9.10.74 Compiler: 1.31.3 ClmImport: 1.36.3 Creation: 2017-10-23 03:36:41 

Crypt Test
error    test passed!
base64   test passed!
RTC/Time not set!
base64   test failed!
 error = -1303
Crypt Test: Return code -1
Sleep 3 seconds to restart...
master-q commented 6 years ago

Following two define macros are needed to fix RTC/Time not set! error:

#elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP)
    #include <time.h>
    #define XTIME(t1)       pic32_time((t1))
    #define XGMTIME(c, t)   gmtime((c))
--snip--
time_t pic32_time(time_t* timer)
--snip--
struct tm* gmtime(const time_t* timer)
master-q commented 6 years ago

I believe we can't implement XTIME() which returns Y2K...

The RTC block has been deprecated from this datasheet in revision *A and later. This block is used by Cypress for internal testing/validation/verification and is not intended for customers to use.

http://www.cypress.com/documentation/datasheets/cyw43907-wiced-ieee-80211-abgn-soc-embedded-applications-processor

master-q commented 6 years ago

I think a data abort exception at RSA test:

$ ./make.sh test.wolfssl_test-CYW943907AEVAL1F-FreeRTOS-LwIP-debug download run
$ picocom -b 115200 /dev/ttyUSB1
--snip--
AES192   test passed!
AES256   test passed!
RANDOM   test passed!
=== EXCEPTION ===
data_abort_handler
DFSR : 0x00001C06
DFAR : 0x00000000
IFSR : 0x00000000
IFAR : 0x00000000
CPSR : 0x00070197
R0   : 0x00000000
R1   : 0x00000020
R2   : 0xFFFFFFFF
R3   : 0x00000000
R4   : 0x005376CC
R5   : 0x005014B0
R6   : 0x06060606
R7   : 0x0004DEBD
R8   : 0x08080808
R9   : 0x09090909
R10  : 0x10101010
R11  : 0x11111111
R12  : 0x005089AC
LR   : 0x004DE9C4
=================
cconlon commented 6 years ago

Thanks for the updates.

We have several ways to plug an entropy source into wolfSSL.

1) Write a new GenerateSeed() function specific to the WICED SDK, in ./wolfcrypt/src/random.c. This function should fill the "output" buffer with "sz" random bytes. This is the most common method we use for new platform ports.

2) Define CUSTOM_RAND_GENERATE to a custom random function that matches the following prototype:

word32 rand_gen(void);

If the function mapped to CUSTOM_RAND_GENERATE returns a type different than a word32, CUSTOM_RAND_TYPE should be defined to that data type.

I believe we can't implement XTIME() which returns Y2K...

A new code block should be added in ./wolfssl/wolfcrypt/wc_port.h which defines XTIME to a function in the WICED SDK that returns the number of seconds since the Unix epoch. Other platform examples of how time was handled can be seen in wc_port.h. If this is not possible, we will need to force the application to define XTIME in their own file. Our UTasker port does this, if you look in ./wolfssl/wolfcrypt/settings.h:

/* user needs to define XTIME to function that provides
 * seconds since Unix epoch */
#ifndef XTIME
    #error XTIME must be defined in wolfSSL settings.h
    /* #define XTIME fnSecondsSinceEpoch */
#endif

I think a data abort exception at RSA test:

The most common reasons for a crash in RSA are:

  1. The stack size of the application is not set high enough.

  2. The application has been compiled with different preprocessor defines than the wolfSSL library / sources have been.

master-q commented 6 years ago
  1. Write a new GenerateSeed() function specific to the WICED SDK, in ./wolfcrypt/src/random.c. This function should fill the "output" buffer with "sz" random bytes. This is the most common method we use for new platform ports.

I choose this method, which is following:

https://github.com/master-q/wolfssl/commit/9e6a2744813c36d842c4ea96867060e2a491859f

master-q commented 6 years ago

@cconlon

If this is not possible, we will need to force the application to define XTIME in their own file. Our UTasker port does this, if you look in ./wolfssl/wolfcrypt/settings.h:

Sorry. I can't understand it.

The uTasker configuration needs XTIME macro out of wolfSSL library. However of course, such XTIME can't be implemented, because there are no RTC on hardware...

master-q commented 6 years ago

Sorry. I can't understand it.

The uTasker configuration needs XTIME macro out of wolfSSL library. However of course, such XTIME can't be implemented, because there are no RTC on hardware...

Or should I the UTC time from NTP?

master-q commented 6 years ago

@cconlon

Sorry. I can't understand it.

The uTasker configuration needs XTIME macro out of wolfSSL library. However of course, such XTIME can't be implemented, because there are no RTC on hardware...

I have an idea from Kojo. I'll try to implement pseudo Unix epoch time.

master-q commented 6 years ago

https://gitlab.com/masterq/WICED-Studio-6.0-wolfSSL/commit/7a77e27e4261969587511f6958ff2ef656d480d5

Pass all of tests with 32kB stack.

master-q commented 6 years ago

I have an idea from Kojo. I'll try to implement pseudo Unix epoch time.

There are some plans:

  1. Calculate Unix epoch time using the time value at building environment.
  2. Calculate Unix epoch time using a constant time value.

1 is better than 2. But 1 needs portable Unix epoch time function/command between Windows/MacOS/Linux. As first step, I should choose 2.

master-q commented 6 years ago

The Unix epoch time can be gotten by following command:

$ date +'%s'
master-q commented 6 years ago
  1. Calculate Unix epoch time using the time value at building environment.

I found better way for 1 with Perl.

https://github.com/master-q/wolfssl/commit/1c3facf0bf9780d2c0a9908457b817378c045076

master-q commented 6 years ago

Publish first version of HTTPS client: https://gitlab.com/masterq/WICED-Studio-6.0-wolfSSL/commit/c663ff228fefcf49fb5791ac6650d106a757e54a which includes Cypress Copyright. Because I copied many code from original WICED source code.

master-q commented 6 years ago

Introduced a make target to switch wolfSSL and mbed TLS:

https://gitlab.com/masterq/WICED-Studio-6.0-wolfSSL/commit/8edd5121edc669d5a18262149887869ad2f45053

master-q commented 6 years ago

Umm... WICED strongly customizes mbed TLS...

$ git grep -i wiced WICED/security/BESL/mbedtls_open/ | wc -l
101
master-q commented 6 years ago

I believe aes_decrypt_ccm() function is hidden in Cypress binary:

$ pwd
/home/kiwamu/Documents/WICED-Studio-6.0/43xxx_Wi-Fi
$ ./make.sh clean && ./make.sh QUIET= snip.https_client-CYW943907AEVAL1F-FreeRTOS-LwIP
$ vi WICED/internal/wiced_cooee.c
--snip--
    /* Decrypt the data */
    {
        uint8_t* cooee_key;
        wiced_dct_read_lock( (void**) &cooee_key, WICED_FALSE, DCT_SECURITY_SECTION, offsetof(platform_dct_security_t, cooee_key), COOEE_KEY_SIZE );

        mbedtls_aes_setkey_dec( &aes_ctx, cooee_key, 128 );

        wiced_dct_read_unlock( cooee_key, WICED_FALSE );
    }

    if (aes_decrypt_ccm( &aes_ctx, content_length, 10, cooee_nonce, sizeof(cooee_nonce),(uint8_t*) cooee_header, &workspace->received_cooee_data[10], &workspace->received_cooee_data[10] ) != 0)
    {
        WPRINT_WICED_INFO( ("Cooee payload decryption failed\n") );
        goto return_with_error;
    }
$ vi WICED/security/BESL/crypto_internal/wiced_security_internal.h
--snip--
/**
 * @brief                   AES-CCM decryption
 *
 * @param[in]  ctx              : AES context
 * @param[in]  length           : Length of the input data
 * @param[in]  aad_length       : Length of the additional associated data
 * @param[in]  nonce            : The nonce to use
 * @param[in]  nonce_length     : Length of nonce.
 * @param[in]  aad_input        : The buffer containing the additional associated data
 * @param[in]  ciphertext_input : Buffer holding the input data
 * @param[out] plaintext_output : Buffer which receives the output plaintext
 */
int aes_decrypt_ccm( mbedtls_aes_context *ctx, uint32_t length, uint32_t aad_length,  const unsigned char *nonce, uint8_t nonce_length, const unsigned char *aad_input, const unsigned char *ciphertext_input, unsigned char *plaintext_output );
$ grep aes_decrypt_ccm ./build/snip.https_client-CYW943907AEVAL1F-FreeRTOS-LwIP/binary/snip.https_client-CYW943907AEVAL1F-FreeRTOS-LwIP.map
 .text.aes_decrypt_ccm
aes_decrypt_ccm                                   ././WICED/security/BESL/BESL_generic.ARM_CR4.release.a(aes-ctr-ccm.o)

Above means the aes_decrypt_ccm is derived from the BESL_generic.ARM_CR4.release.a file. And source codes of the BESL_generic.ARM_CR4.release.a is not published at the internet.

Tentatively, I choose a way to overwrite above internal API using wolfSSL API.

master-q commented 6 years ago

There is a semantic gap between aes_decrypt_ccm and wc_AesCcmDecrypt:

 WOLFSSL_API int  wc_AesCcmDecrypt(Aes* aes, byte* out,
                                   const byte* in, word32 inSz,
                                   const byte* nonce, word32 nonceSz,
                                   const byte* authTag, word32 authTagSz,
                                   const byte* authIn, word32 authInSz);

What does aad_input means? Is it equivalent to authTag?

master-q commented 6 years ago

I believe struct WOLFSSL_SESSION is equivalent to mbedtls_ssl_session.

master-q commented 6 years ago

I think WOLFSSL_X509_CHAIN is equivalent to mbedtls_x509_crt.

master-q commented 6 years ago

The BESL library is too big to re-write it with wolfSSL. How about start on smaller subset?

$ vi WICED/security/BESL/BESL.mk
--snip--
$(NAME)_SOURCES += host/WICED/besl_host.c \
                   host/WICED/wiced_tls.c \
                   host/WICED/wiced_wps.c \
                   host/WICED/wiced_p2p.c \
                   host/WICED/cipher_suites.c \
                   host/WICED/tls_cipher_suites.c \
                   host/WICED/dtls_cipher_suites.c \
                   host/WICED/p2p_internal.c \
                   host/WICED/wiced_supplicant.c \
                   P2P/p2p_events.c \
                   P2P/p2p_frame_writer.c \
                   host/WICED/wiced_dtls.c
master-q commented 6 years ago

After my long reading code, I believe we should create WOLFSSL_CTX before reading PEM and key, to store them on the structure. It means we should change following structure in original WICED code:

typedef struct
{
    union
    {
        wiced_tls_psk_key_t psk_key;
        mbedtls_pk_context  private_key;
    };
    mbedtls_x509_crt        certificate;
    wiced_tls_sign_certificate_verify custom_sign;
} wiced_tls_identity_t;

as following:

typedef struct
{
    WOLFSSL_CTX* ctx;
    wiced_tls_sign_certificate_verify custom_sign; // How to use with wolfSSL?
} wiced_tls_identity_t;

It seems like a bit strange name. Why do we call WOLFSSL_CTX as identity? It's caused by following initialization flow at WICED:

typedef struct mbedtls_ssl_context  wiced_tls_workspace_t;
typedef struct mbedtls_ssl_session  wiced_tls_session_t;
typedef struct mbedtls_x509_crt wiced_tls_certificate_t;

typedef int (*wiced_tls_sign_certificate_verify)(  void* key ,rsa_hash_id_t hash_id, int32_t hashlen, const unsigned char *hash, unsigned char *sign, uint32_t* key_length, wiced_tls_key_type_t type );

typedef struct
{
    union
    {
        wiced_tls_psk_key_t psk_key;
        mbedtls_pk_context  private_key;
    };
    mbedtls_x509_crt        certificate;
    wiced_tls_sign_certificate_verify custom_sign;
} wiced_tls_identity_t;

typedef struct
{
    uint32_t                 context_id;
    wiced_tls_workspace_t    context;
    wiced_tls_session_t*     session;
    wiced_tls_identity_t*    identity;
} wiced_tls_context_t;

wiced_https_get()
=> wiced_tls_context_t *context;
   wiced_tls_identity_t *tls_identity = NULL;
   tls_identity = ( wiced_tls_identity_t* ) malloc_named ("tls_identity", sizeof( wiced_tls_identity_t ));
   wiced_tls_init_identity( tls_identity, dct_security->private_key, strlen( dct_security->private_key ), (uint8_t*) dct_security->certificate, strlen( dct_security->certificate ) );
   => mbedtls_x509_crt_init( &identity->certificate );
      mbedtls_x509_crt_parse( &identity->certificate, (const unsigned char *) certificate_data, certificate_length );
      mbedtls_pk_init( &identity->private_key );
      mbedtls_pk_parse_key( &identity->private_key, (const unsigned char *) private_key, key_length, NULL, 0 );
   wiced_tcp_create_socket( &socket, WICED_STA_INTERFACE ) ) != WICED_SUCCESS );
   context = MALLOC_OBJECT( "HTTP Client TLS Context", wiced_tls_context_t );
   socket.context_malloced = WICED_TRUE;
   wiced_tls_init_context( context, tls_identity, peer_cn );
   => context->context.conf = tls_host_malloc ("tls", sizeof(mbedtls_ssl_config));
      context->context_id = WICED_TLS_CONTEXT_ID;
      context->identity = identity;
      ((mbedtls_ssl_config*)context->context.conf)->peer_cn = peer_cn;
   wiced_tcp_enable_tls( &socket, context );
   => socket->tls_context = context;
   wiced_tcp_connect( &socket, address, 443, 20000 );
   => wiced_tcp_start_tls( socket, WICED_TLS_AS_CLIENT, WICED_TLS_DEFAULT_VERIFICATION );
      => wiced_generic_start_tls_with_ciphers( socket->tls_context, socket, type, verification, NULL, TLS_TCP_TRANSPORT );
         => mbedtls_ssl_config* conf = (mbedtls_ssl_config*) tls_context->context.conf;

As above, WICED call mbedtls_x509_crt_parse and mbedtls_pk_parse_key before calling wiced_tls_init_context.

Totally, breaking the name convention is better than destroying WICED external API.

cconlon commented 6 years ago

What does aad_input means? Is it equivalent to authTag?

My guess is that "aad_input" is referring to AES-CCM's optional additional authenticated data (AAD). For wc_AesCcmDecrypt() this would be authIn.

After my long reading code, I believe we should create WOLFSSL_CTX before reading PEM and key, to store them on the structure.

A user needs to create a WOLFSSL_CTX with wolfSSL_CTX_new( ) before any keys or certificates (or other CTX-level settings can be loaded into the context.

It seems like a bit strange name. Why do we call WOLFSSL_CTX as identity?

When I read your code section above, it looks like WICED calls that structure an "identity" because it is representing the identity of the client. That identity looks like it could be represented through a PSK (pre-shared key) or X.509 certificate.

It seems like mbedTLS first loads a certificate and key into separate structures - mbedtls_x509_crt for the certificate, and either wiced_tls_psk_key_t (in the case PSK's are being used) or mbedtls_pk_context (for a normal RSA/ECC key). wolfSSL doesn't require users to create individual structures first. Users/apps just load a certificate file into a WOLFSSL_CTX with wolfSSL_CTX_use_certificate_file() or wolfSSL_CTX_use_certificate_buffer() and a private key into the WOLFSSL_CTX with wolfSSL_CTX_use_PrivateKey_file() or wolfSSL_CTX_use_PrivateKey_buffer(). The wolfSSL examples that ship with our download are good examples of doing this. You can also look in our examples repository: https://github.com/wolfSSL/wolfssl-examples/tree/master/tls

In the wolfSSL case, wiced_tls_init_identity() should probably call wolfSSL_CTX_new(), wolfSSL_CTX_use_certificate_file/wolfSSL_CTX_use_certificate_buffer() and wolfSSL_CTX_use_PrivateKey_file/wolfSSL_CTX_use_PrivateKey_buffer().

master-q commented 6 years ago

My guess is that "aad_input" is referring to AES-CCM's optional additional authenticated data (AAD). For wc_AesCcmDecrypt() this would be authIn.

I think you are right. Thanks a lot.

/**
 * @brief                   AES-CCM encryption
 *
 * @param[in]  ctx               : AES context
 * @param[in]  length            : Length of the input data
 * @param[in]  aad_length        : Length of the additional associated data
 * @param[in]  nonce             : The nonce to use
 * @param[in]  nonce_length      : Length of nonce.
 * @param[in]  aad_input         : The buffer containing the additional associated data
 * @param[in]  plaintext_input   : Buffer holding the input data
 * @param[out] ciphertext_output : Buffer which receives the output ciphertext
 * @param[out] mac_output        : Buffer which recieves the output MAC
 */
int aes_encrypt_ccm( mbedtls_aes_context *ctx, uint32_t length, uint32_t aad_length, const unsigned char *nonce, uint8_t nonce_length, const unsigned char *aad_input, const unsigned char *plaintext_input, unsigned char *ciphertext_output, unsigned char mac_output[8] );
master-q commented 6 years ago

A user needs to create a WOLFSSL_CTX with wolfSSL_CTX_new( ) before any keys or certificates (or other CTX-level settings can be loaded into the context.

Umm... It means we should cache the keys and certificates into wiced_tls_identity_t.

master-q commented 6 years ago

When I read your code section above, it looks like WICED calls that structure an "identity" because it is representing the identity of the client. That identity looks like it could be represented through a PSK (pre-shared key) or X.509 certificate.

Yes.

It seems like mbedTLS first loads a certificate and key into separate structures - mbedtls_x509_crt for the certificate, and either wiced_tls_psk_key_t (in the case PSK's are being used) or mbedtls_pk_context (for a normal RSA/ECC key). wolfSSL doesn't require users to create individual structures first. Users/apps just load a certificate file into a WOLFSSL_CTX with wolfSSL_CTX_use_certificate_file() or wolfSSL_CTX_use_certificate_buffer() and a private key into the WOLFSSL_CTX with wolfSSL_CTX_use_PrivateKey_file() or wolfSSL_CTX_use_PrivateKey_buffer(). The wolfSSL examples that ship with our download are good examples of doing this. You can also look in our examples repository: https://github.com/wolfSSL/wolfssl-examples/tree/master/tls

I understand above, now.

In the wolfSSL case, wiced_tls_init_identity() should probably call wolfSSL_CTX_new(), wolfSSL_CTX_use_certificate_file/wolfSSL_CTX_use_certificate_buffer() and wolfSSL_CTX_use_PrivateKey_file/wolfSSL_CTX_use_PrivateKey_buffer().

I think it means:

typedef struct
{
    WOLFSSL_CTX*                      ctx;
    wiced_tls_sign_certificate_verify custom_sign; // Not used
} wiced_tls_identity_t;

typedef struct
{
    uint32_t                 context_id;
    WOLFSSL*                 ssl;
    wiced_tls_identity_t*    identity;
} wiced_tls_context_t;