Remove unused wolfSSL files. (#197)

* Remove unused wolfSSL files.

* Add back some removed ciphers.

* Update VS project file.
This commit is contained in:
Ming Yue 2020-08-11 17:06:59 -07:00 committed by GitHub
parent 0e0edd96e8
commit 70dcbe4527
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
974 changed files with 7 additions and 210690 deletions

View file

@ -1,103 +0,0 @@
# wolfCrypt Benchmarks
Tool for performing cryptographic algorithm benchmarking.
## Measurements
* Symmetric algorithms like AES and ChaCha20 are measured in Killobytes (KB) or Megabytes (MB) per second.
* Asymmetric algorithms like RSA and ECC are measured using Operations Per Second (Ops) per second.
## Usage
```sh
./wolfcrypt/benchmark/benchmark -?
benchmark
-? <num> Help, print this usage
0: English, 1: Japanese
-csv Print terminal output in csv format
-base10 Display bytes as power of 10 (eg 1 kB = 1000 Bytes)
-no_aad No additional authentication data passed.
-dgst_full Full digest operation performed.
-rsa_sign Measure RSA sign/verify instead of encrypt/decrypt.
<keySz> -rsa-sz
Measure RSA <key size> performance.
-<alg> Algorithm to benchmark. Available algorithms include:
cipher aes-cbc aes-gcm aes-ecb aes-xts aes-cfb aes-ctr aes-ccm
camellia arc4 hc128 rabbit chacha20 chacha20-poly1305 des idea
digest md5 poly1305 sha sha2 sha224 sha256 sha384 sha512 sha3
sha3-224 sha3-256 sha3-384 sha3-512 ripemd
mac cmac hmac hmac-md5 hmac-sha hmac-sha224 hmac-sha256
hmac-sha384 hmac-sha512 pbkdf2
asym rsa-kg rsa rsa-sz dh ecc-kg ecc ecc-enc curve25519_kg x25519
ed25519-kg ed25519
other rng scrypt
-lng <num> Display benchmark result by specified language.
0: English, 1: Japanese
<num> Size of block in bytes
```
The `-base10` option shows as thousands of bytes (kB).
## Example Output
Run on Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz.
```sh
./configure --enable-intelasm --enable-aesni --enable-sp --enable-sp-asm && make
./wolfcrypt/benchmark/benchmark
------------------------------------------------------------------------------
wolfSSL version 4.0.0
------------------------------------------------------------------------------
wolfCrypt Benchmark (block bytes 1048576, min 1.0 sec each)
RNG 180 MB took 1.022 seconds, 176.201 MB/s Cycles per byte = 16.76
AES-128-CBC-enc 1250 MB took 1.002 seconds, 1247.878 MB/s Cycles per byte = 2.37
AES-128-CBC-dec 4595 MB took 1.001 seconds, 4591.703 MB/s Cycles per byte = 0.64
AES-192-CBC-enc 1005 MB took 1.003 seconds, 1002.018 MB/s Cycles per byte = 2.95
AES-192-CBC-dec 4345 MB took 1.000 seconds, 4344.744 MB/s Cycles per byte = 0.68
AES-256-CBC-enc 905 MB took 1.005 seconds, 900.386 MB/s Cycles per byte = 3.28
AES-256-CBC-dec 3255 MB took 1.001 seconds, 3251.618 MB/s Cycles per byte = 0.91
AES-128-GCM-enc 4730 MB took 1.001 seconds, 4726.267 MB/s Cycles per byte = 0.62
AES-128-GCM-dec 5140 MB took 1.000 seconds, 5137.596 MB/s Cycles per byte = 0.57
AES-192-GCM-enc 4475 MB took 1.001 seconds, 4471.056 MB/s Cycles per byte = 0.66
AES-192-GCM-dec 3405 MB took 1.001 seconds, 3403.179 MB/s Cycles per byte = 0.87
AES-256-GCM-enc 2640 MB took 1.000 seconds, 2638.905 MB/s Cycles per byte = 1.12
AES-256-GCM-dec 2780 MB took 1.001 seconds, 2776.632 MB/s Cycles per byte = 1.06
CHACHA 2615 MB took 1.000 seconds, 2614.357 MB/s Cycles per byte = 1.13
CHA-POLY 1490 MB took 1.001 seconds, 1488.344 MB/s Cycles per byte = 1.98
MD5 440 MB took 1.010 seconds, 435.763 MB/s Cycles per byte = 6.78
POLY1305 4900 MB took 1.001 seconds, 4896.430 MB/s Cycles per byte = 0.60
SHA 515 MB took 1.011 seconds, 509.459 MB/s Cycles per byte = 5.80
SHA-224 425 MB took 1.005 seconds, 422.737 MB/s Cycles per byte = 6.98
SHA-256 420 MB took 1.006 seconds, 417.312 MB/s Cycles per byte = 7.08
SHA-384 615 MB took 1.003 seconds, 613.018 MB/s Cycles per byte = 4.82
SHA-512 560 MB took 1.007 seconds, 556.230 MB/s Cycles per byte = 5.31
SHA3-224 295 MB took 1.003 seconds, 294.133 MB/s Cycles per byte = 10.04
SHA3-256 280 MB took 1.003 seconds, 279.088 MB/s Cycles per byte = 10.58
SHA3-384 215 MB took 1.002 seconds, 214.654 MB/s Cycles per byte = 13.76
SHA3-512 145 MB took 1.005 seconds, 144.266 MB/s Cycles per byte = 20.47
HMAC-MD5 485 MB took 1.004 seconds, 483.019 MB/s Cycles per byte = 6.11
HMAC-SHA 505 MB took 1.006 seconds, 502.159 MB/s Cycles per byte = 5.88
HMAC-SHA224 415 MB took 1.007 seconds, 411.965 MB/s Cycles per byte = 7.17
HMAC-SHA256 380 MB took 1.002 seconds, 379.398 MB/s Cycles per byte = 7.78
HMAC-SHA384 610 MB took 1.006 seconds, 606.370 MB/s Cycles per byte = 4.87
HMAC-SHA512 620 MB took 1.001 seconds, 619.377 MB/s Cycles per byte = 4.77
RSA 2048 public 52000 ops took 1.001 sec, avg 0.019 ms, 51932.223 ops/sec
RSA 2048 private 1700 ops took 1.022 sec, avg 0.601 ms, 1662.697 ops/sec
DH 2048 key gen 3491 ops took 1.000 sec, avg 0.286 ms, 3490.745 ops/sec
DH 2048 agree 3500 ops took 1.014 sec, avg 0.290 ms, 3452.191 ops/sec
ECC 256 key gen 88961 ops took 1.000 sec, avg 0.011 ms, 88960.279 ops/sec
ECDHE 256 agree 20700 ops took 1.005 sec, avg 0.049 ms, 20605.239 ops/sec
ECDSA 256 sign 53200 ops took 1.001 sec, avg 0.019 ms, 53157.214 ops/sec
ECDSA 256 verify 17200 ops took 1.004 sec, avg 0.058 ms, 17124.208 ops/sec
Benchmark complete
```
## Windows Visual Studio
For building wolfCrypt Benchmark project in Visual Studio open the `benchmark.sln`. For newer Visual Studio version it may prompt for a one-way upgrade. Then you may have to right-click on the solution and choose `Retarget solution` to update the project files for your Visual Studio version.
If you see an error about `rc.exe` then you'll need to update the "Target Platform Version". You can do this by right-clicking on the benchmark project -> General -> "Target Platform Version" and changing to 8.1 (needs to match the wolfssl library project).
This solution includes the wolfSSL library project at `<wolfssl-root>wolfssl.vcxproj` and will compile the library, then the benchmark project.

View file

@ -1,111 +0,0 @@
/* wolfcrypt/benchmark/benchmark.h
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef WOLFCRYPT_BENCHMARK_H
#define WOLFCRYPT_BENCHMARK_H
#ifdef __cplusplus
extern "C" {
#endif
/* run all benchmark entry */
#ifdef HAVE_STACK_SIZE
THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args);
#else
int benchmark_test(void *args);
#endif
/* individual benchmarks */
int benchmark_init(void);
int benchmark_free(void);
void benchmark_configure(int block_size);
void bench_des(int);
void bench_idea(void);
void bench_arc4(int);
void bench_hc128(void);
void bench_rabbit(void);
void bench_chacha(void);
void bench_chacha20_poly1305_aead(void);
void bench_aescbc(int);
void bench_aesgcm(int);
void bench_aesccm(void);
void bench_aesecb(int);
void bench_aesxts(void);
void bench_aesctr(void);
void bench_aescfb(void);
void bench_aesofb(void);
void bench_poly1305(void);
void bench_camellia(void);
void bench_md5(int);
void bench_sha(int);
void bench_sha224(int);
void bench_sha256(int);
void bench_sha384(int);
void bench_sha512(int);
void bench_sha3_224(int);
void bench_sha3_256(int);
void bench_sha3_384(int);
void bench_sha3_512(int);
int bench_ripemd(void);
void bench_cmac(void);
void bench_scrypt(void);
void bench_hmac_md5(int);
void bench_hmac_sha(int);
void bench_hmac_sha224(int);
void bench_hmac_sha256(int);
void bench_hmac_sha384(int);
void bench_hmac_sha512(int);
void bench_rsaKeyGen(int);
void bench_rsaKeyGen_size(int, int);
void bench_rsa(int);
void bench_rsa_key(int, int);
void bench_dh(int);
void bench_eccMakeKey(int);
void bench_ecc(int);
void bench_eccEncrypt(void);
void bench_curve25519KeyGen(void);
void bench_curve25519KeyAgree(void);
void bench_ed25519KeyGen(void);
void bench_ed25519KeySign(void);
void bench_curve448KeyGen(void);
void bench_curve448KeyAgree(void);
void bench_ed448KeyGen(void);
void bench_ed448KeySign(void);
void bench_ntru(void);
void bench_ntruKeyGen(void);
void bench_rng(void);
void bench_blake2b(void);
void bench_blake2s(void);
void bench_pbkdf2(void);
void bench_stats_print(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WOLFCRYPT_BENCHMARK_H */

View file

@ -21,7 +21,7 @@
#if !defined(WOLFSSL_EVP_INCLUDED)
#ifndef WOLFSSL_IGNORE_FILE_WARN
// #warning evp.c does not need to be compiled separately from ssl.c
#warning evp.c does not need to be compiled separately from ssl.c
#endif
#elif defined(WOLFCRYPT_ONLY)
#else

View file

@ -1,109 +0,0 @@
# ESP32 Port
Support for the ESP32-WROOM-32 on-board crypto hardware acceleration for symmetric AES, SHA1/SHA256/SHA384/SHA512 and RSA primitive including mul, mulmod and exptmod.
## ESP32 Acceleration
For detail about ESP32 HW Acceleration, you can find in [Technical Reference Manual](https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf)
### Building
To enable hw acceleration :
Uncomment out #define WOLFSSL_ESPIDF in /path/to/wolfssl/wolfssl/wolfcrypt/settings.h
Uncomment out #define WOLFSSL_ESPWROOM32 in /path/to/wolfssl/wolfssl/wolfcrypt/settings.h
To disable portions of the hardware acceleration you can optionally define:
```
/* Disabled SHA, AES and RSA acceleration */
#define NO_ESP32WROOM32_CRYPT
/* Disabled AES acceleration */
#define NO_WOLFSSL_ESP32WROOM32_CRYPT_AES
/* Disabled SHA acceleration */
#define NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH
/* Disabled RSA Primitive acceleration */
#define NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI
```
### Coding
In your application you must include <wolfssl/wolfcrypt/settings.h> before any other wolfSSL headers. If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own `user_settings.h` file. You can find a good reference for this in `IDE/GCC-ARM/Header/user_settings.h`.
### Benchmarks
w/ USE_FAST_MATH and WOLFSSL_SMALL_STACK options
Software only implementation :
```
AES-128-CBC-enc 1 MB took 1.001 seconds, 1.146 MB/s
AES-128-CBC-dec 1 MB took 1.017 seconds, 1.104 MB/s
AES-192-CBC-enc 1 MB took 1.018 seconds, 1.055 MB/s
AES-192-CBC-dec 1 MB took 1.006 seconds, 1.019 MB/s
AES-256-CBC-enc 1000 KB took 1.000 seconds, 1000.000 KB/s
AES-256-CBC-dec 975 KB took 1.007 seconds, 968.222 KB/s
AES-128-GCM-enc 350 KB took 1.055 seconds, 331.754 KB/s
AES-128-GCM-dec 350 KB took 1.054 seconds, 332.068 KB/s
AES-192-GCM-enc 325 KB took 1.013 seconds, 320.829 KB/s
AES-192-GCM-dec 325 KB took 1.013 seconds, 320.829 KB/s
AES-256-GCM-enc 325 KB took 1.041 seconds, 312.200 KB/s
AES-256-GCM-dec 325 KB took 1.041 seconds, 312.200 KB/s
SHA 6 MB took 1.004 seconds, 5.714 MB/s
SHA-256 2 MB took 1.006 seconds, 1.747 MB/s
SHA-384 1 MB took 1.011 seconds, 1.159 MB/s
SHA-512 1 MB took 1.009 seconds, 1.161 MB/s
HMAC-SHA 6 MB took 1.001 seconds, 5.634 MB/s
HMAC-SHA256 2 MB took 1.000 seconds, 1.733 MB/s
HMAC-SHA384 1 MB took 1.004 seconds, 1.046 MB/s
HMAC-SHA512 1 MB took 1.002 seconds, 1.048 MB/s
RSA 2048 public 16 ops took 1.056 sec, avg 66.000 ms, 15.152 ops/sec
RSA 2048 private 2 ops took 2.488 sec, avg 1244.000 ms, 0.804 ops/sec
ECC 256 key gen 4 ops took 1.101 sec, avg 275.250 ms, 3.633 ops/sec
ECDHE 256 agree 4 ops took 1.098 sec, avg 274.500 ms, 3.643 ops/sec
ECDSA 256 sign 4 ops took 1.111 sec, avg 277.750 ms, 3.600 ops/sec
ECDSA 256 verify 2 ops took 1.099 sec, avg 549.500 ms, 1.820 ops/sec
```
Hardware Acceleration :
```
AES-128-CBC-enc 6 MB took 1.004 seconds, 5.958 MB/s
AES-128-CBC-dec 5 MB took 1.002 seconds, 5.287 MB/s
AES-192-CBC-enc 6 MB took 1.004 seconds, 5.958 MB/s
AES-192-CBC-dec 5 MB took 1.002 seconds, 5.287 MB/s
AES-256-CBC-enc 6 MB took 1.001 seconds, 5.951 MB/s
AES-256-CBC-dec 5 MB took 1.004 seconds, 5.277 MB/s
AES-128-GCM-enc 375 KB took 1.067 seconds, 351.453 KB/s
AES-128-GCM-dec 375 KB took 1.067 seconds, 351.453 KB/s
AES-192-GCM-enc 350 KB took 1.010 seconds, 346.535 KB/s
AES-192-GCM-dec 350 KB took 1.009 seconds, 346.878 KB/s
AES-256-GCM-enc 350 KB took 1.016 seconds, 344.488 KB/s
AES-256-GCM-dec 350 KB took 1.016 seconds, 344.488 KB/s
SHA 14 MB took 1.000 seconds, 14.062 MB/s
SHA-256 15 MB took 1.000 seconds, 15.234 MB/s
SHA-384 17 MB took 1.000 seconds, 17.383 MB/s
SHA-512 18 MB took 1.001 seconds, 17.512 MB/s
HMAC-SHA 14 MB took 1.000 seconds, 13.818 MB/s
HMAC-SHA256 15 MB took 1.001 seconds, 14.951 MB/s
HMAC-SHA384 17 MB took 1.001 seconds, 16.683 MB/s
HMAC-SHA512 17 MB took 1.000 seconds, 16.943 MB/s
RSA 2048 public 20 ops took 1.017 sec, avg 50.850 ms, 19.666 ops/sec
RSA 2048 private 4 ops took 1.059 sec, avg 264.750 ms, 3.777 ops/sec
ECC 256 key gen 4 ops took 1.092 sec, avg 273.000 ms, 3.663 ops/sec
ECDHE 256 agree 4 ops took 1.089 sec, avg 272.250 ms, 3.673 ops/sec
ECDSA 256 sign 4 ops took 1.101 sec, avg 275.250 ms, 3.633 ops/sec
ECDSA 256 verify 2 ops took 1.092 sec, avg 546.000 ms, 1.832 ops/sec
```
Condition :
- Model : ESP32-WROOM-32
- CPU Speed: 240Mhz
- ESP-IDF : v3.3-beta1-39-g6cb37ecc5(commit hash : 6cb37ecc5)
- OS : Ubuntu 18.04.1 LTS (Bionic Beaver)
## Support
Email us at [support@wolfssl.com](mailto:support@wolfssl.com).

View file

@ -1,299 +0,0 @@
/* esp32_aes.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <string.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifndef NO_AES
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
#include <wolfssl/wolfcrypt/aes.h>
#include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
static const char* TAG = "wolf_hw_aes";
/* mutex */
static wolfSSL_Mutex aes_mutex;
static int espaes_CryptHwMutexInit = 0;
/*
* lock hw engine.
* this should be called before using engine.
*/
static int esp_aes_hw_InUse()
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_aes_hw_InUse");
if(espaes_CryptHwMutexInit == 0) {
ret = esp_CryptHwMutexInit(&aes_mutex);
if(ret == 0){
espaes_CryptHwMutexInit = 1;
} else {
ESP_LOGE(TAG, "aes mutx initialization failed.");
return -1;
}
}
/* lock hardware */
ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY);
if(ret != 0) {
ESP_LOGE(TAG, "aes engine lock failed.");
return -1;
}
/* Enable AES hardware */
periph_module_enable(PERIPH_AES_MODULE);
ESP_LOGV(TAG, "leave esp_aes_hw_InUse");
return ret;
}
/*
* release hw engine
*/
static void esp_aes_hw_Leave( void )
{
ESP_LOGV(TAG, "enter esp_aes_hw_Leave");
/* Disable AES hardware */
periph_module_disable(PERIPH_AES_MODULE);
/* unlock */
esp_CryptHwMutexUnLock(&aes_mutex);
ESP_LOGV(TAG, "leave esp_aes_hw_Leave");
}
/*
* set key to hardware key registers.
*/
static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
{
int i;
word32 mode_ = 0;
ESP_LOGV(TAG, "enter esp_aes_hw_Set_KeyMode");
/* check mode */
if(mode == ESP32_AES_UPDATEKEY_ENCRYPT) {
mode_ = 0;
} else if(mode == ESP32_AES_UPDATEKEY_DECRYPT){
mode_ = 4;
} else {
ESP_LOGE(TAG, "unexpected error.");
return;
}
/* update key */
for(i=0;i<(ctx->keylen)/sizeof(word32);i++){
DPORT_REG_WRITE(AES_KEY_BASE + (i*4), *(((word32*)ctx->key) + i));
}
/* mode
* 0 AES-128 Encryption
* 1 AES-192 Encryption
* 2 AES-256 Encryption
* 4 AES-128 Decryption
* 5 AES-192 Decryption
* 6 AES-256 Decryption
*/
switch(ctx->keylen){
case 24: mode_ += 1; break;
case 32: mode_ += 2; break;
default: break;
}
DPORT_REG_WRITE(AES_MODE_REG, mode_);
ESP_LOGV(TAG, "leave esp_aes_hw_Setkey");
}
/*
* Process a one block of AES
*/
static void esp_aes_bk(const byte* in, byte* out)
{
const word32 *inwords = (const word32 *)in;
word32 *outwords = (word32 *)out;
ESP_LOGV(TAG, "enter esp_aes_bk");
/* copy text for encrypting/decrypting blocks */
DPORT_REG_WRITE(AES_TEXT_BASE, inwords[0]);
DPORT_REG_WRITE(AES_TEXT_BASE + 4, inwords[1]);
DPORT_REG_WRITE(AES_TEXT_BASE + 8, inwords[2]);
DPORT_REG_WRITE(AES_TEXT_BASE + 12, inwords[3]);
/* start engine */
DPORT_REG_WRITE(AES_START_REG, 1);
/* wait until finishing the process */
while(1) {
if(DPORT_REG_READ(AES_IDLE_REG) == 1)
break;
}
/* read-out blocks */
esp_dport_access_read_buffer(outwords, AES_TEXT_BASE, 4);
ESP_LOGV(TAG, "leave esp_aes_bk");
}
/*
* wc_esp32AesEncrypt
* @brief: a one block encrypt of the input block, into the output block
* @param aes: a pointer of the AES object used to encrypt data
* @param in : a pointer of the input buffer containing plain text to be encrypted
* @param out: a pointer of the output buffer in which to store the cipher text of
* the encrypted message
*/
int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out)
{
ESP_LOGV(TAG, "enter wc_esp32AesEncrypt");
/* lock the hw engine */
esp_aes_hw_InUse();
/* load the key into the register */
esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT);
/* process a one block of AES */
esp_aes_bk(in, out);
/* release hw */
esp_aes_hw_Leave();
return 0;
}
/*
* wc_esp32AesDecrypt
* @brief: a one block decrypt of the input block, into the output block
* @param aes: a pointer of the AES object used to decrypt data
* @param in : a pointer of the input buffer containing plain text to be decrypted
* @param out: a pointer of the output buffer in which to store the cipher text of
* the decrypted message
*/
int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out)
{
ESP_LOGV(TAG, "enter wc_esp32AesDecrypt");
/* lock the hw engine */
esp_aes_hw_InUse();
/* load the key into the register */
esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
/* process a one block of AES */
esp_aes_bk(in, out);
/* release hw engine */
esp_aes_hw_Leave();
return 0;
}
/*
* wc_esp32AesCbcEncrypt
* @brief: Encrypts a plain text message from the input buffer, and places the
* resulting cipher text into the output buffer using cipher block chaining
* with AES.
* @param aes: a pointer of the AES object used to encrypt data
* @param out: a pointer of the output buffer in which to store the cipher text of
* the encrypted message
* @param in : a pointer of the input buffer containing plain text to be encrypted
* @param sz : size of input message
*/
int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
int i;
int offset = 0;
word32 blocks = (sz / AES_BLOCK_SIZE);
byte *iv;
byte temp_block[AES_BLOCK_SIZE];
ESP_LOGV(TAG, "enter wc_esp32AesCbcEncrypt");
iv = (byte*)aes->reg;
esp_aes_hw_InUse();
esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT);
while (blocks--) {
XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
/* XOR block with IV for CBC */
for (i = 0; i < AES_BLOCK_SIZE; i++)
temp_block[i] ^= iv[i];
esp_aes_bk(temp_block, (out + offset));
offset += AES_BLOCK_SIZE;
/* store IV for next block */
XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
}
esp_aes_hw_Leave();
ESP_LOGV(TAG, "leave wc_esp32AesCbcEncrypt");
return 0;
}
/*
* wc_esp32AesCbcDecrypt
* @brief: Encrypts a plain text message from the input buffer, and places the
* resulting cipher text into the output buffer using cipher block chaining
* with AES.
* @param aes: a pointer of the AES object used to decrypt data
* @param out: a pointer of the output buffer in which to store the cipher text of
* the decrypted message
* @param in : a pointer of the input buffer containing plain text to be decrypted
* @param sz : size of input message
*/
int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
int i;
int offset = 0;
word32 blocks = (sz / AES_BLOCK_SIZE);
byte* iv;
byte temp_block[AES_BLOCK_SIZE];
ESP_LOGV(TAG, "enter wc_esp32AesCbcDecrypt");
iv = (byte*)aes->reg;
esp_aes_hw_InUse();
esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
while (blocks--) {
XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
esp_aes_bk((in + offset), (out + offset));
/* XOR block with IV for CBC */
for (i = 0; i < AES_BLOCK_SIZE; i++)
(out + offset)[i] ^= iv[i];
/* store IV for next block */
XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
offset += AES_BLOCK_SIZE;
}
esp_aes_hw_Leave();
ESP_LOGV(TAG, "leave wc_esp32AesCbcDecrypt");
return 0;
}
#endif /* WOLFSSL_ESP32WROOM32_CRYPT */
#endif /* NO_AES */

View file

@ -1,514 +0,0 @@
/* esp32_mp.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <string.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include "wolfssl/wolfcrypt/logging.h"
#if !defined(NO_RSA) || defined(HAVE_ECC)
#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/tfm.h>
static const char* const TAG = "wolfssl_mp";
#define ESP_HW_RSAMAX_BIT 4096
#define ESP_HW_MULTI_RSAMAX_BITS 2048
#define ESP_HW_RSAMIN_BIT 512
#define BYTE_TO_WORDS(s) (((s+3)>>2)) /* (s+(4-1))/ 4 */
#define BITS_TO_WORDS(s) (((s+31)>>3)>>2) /* (s+(32-1))/ 8/ 4*/
#define MP_NG -1
/* mutex */
static wolfSSL_Mutex mp_mutex;
static int espmp_CryptHwMutexInit = 0;
/*
* check if the hw is ready before accessing it
*/
static int esp_mp_hw_wait_clean()
{
int timeout = 0;
while(++timeout < ESP_RSA_TIMEOUT && DPORT_REG_READ(RSA_CLEAN_REG) != 1){}
if(timeout >= ESP_RSA_TIMEOUT) {
ESP_LOGE(TAG, "waiting hw ready is time-outed.");
return MP_NG;
}
return MP_OKAY;
}
/*
* lock hw engine.
* this should be called before using engine.
*/
static int esp_mp_hw_lock()
{
int ret = 0;
if(espmp_CryptHwMutexInit == 0) {
ret = esp_CryptHwMutexInit(&mp_mutex);
if(ret == 0){
espmp_CryptHwMutexInit = 1;
} else {
ESP_LOGE(TAG, "mp mutx initialization failed.");
return MP_NG;
}
}
/* lock hardware */
ret = esp_CryptHwMutexLock(&mp_mutex, portMAX_DELAY);
if(ret != 0) {
ESP_LOGE(TAG, "mp engine lock failed.");
return MP_NG;
}
/* Enable RSA hardware */
periph_module_enable(PERIPH_RSA_MODULE);
return ret;
}
/*
* Release hw engine
*/
static void esp_mp_hw_unlock( void )
{
/* Disable RSA hardware */
periph_module_disable(PERIPH_RSA_MODULE);
/* unlock */
esp_CryptHwMutexUnLock(&mp_mutex);
}
/* this is based on an article by Cetin Kaya Koc, A New Algorithm for Inversion*/
/* mod p^k, June 28 2017. */
static int esp_calc_Mdash(mp_int *M, word32 k, mp_digit* md)
{
int i;
int xi;
int b0 = 1;
int bi;
word32 N = 0;
word32 x;
N = M->dp[0];
bi = b0;
x = 0;
for(i = 0; i < k; i++) {
xi = bi % 2;
if(xi < 0){
xi *= -1;
}
bi = (bi - N * xi) / 2;
x |= (xi << i);
}
/* 2's complement */
*md = ~x + 1;
return MP_OKAY;
}
/* start hw process */
static void process_start(word32 reg)
{
/* clear interrupt */
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
/* start process */
DPORT_REG_WRITE(reg, 1);
}
/* wait until done */
static int wait_uitil_done(word32 reg)
{
int timeout = 0;
/* wait until done && not timeout */
while(1) {
if(++timeout < ESP_RSA_TIMEOUT && DPORT_REG_READ(reg) == 1){
break;
}
}
/* clear interrupt */
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
if(timeout >= ESP_RSA_TIMEOUT) {
ESP_LOGE(TAG, "rsa operation is time-outed.");
return MP_NG;
}
return MP_OKAY;
}
/* read data from memory into mp_init */
static void esp_memblock_to_mpint(word32 mem_address, mp_int* mp, word32 numwords)
{
esp_dport_access_read_buffer((uint32_t*)mp->dp, mem_address, numwords);
mp->used = numwords;
}
/* write mp_init into memory block */
static void esp_mpint_to_memblock(word32 mem_address, const mp_int* mp,
const word32 bits,
const word32 hwords)
{
word32 i;
word32 len = (bits / 8 + ((bits & 7) != 0 ? 1 : 0));
len = (len+sizeof(word32)-1)/sizeof(word32);
for(i=0;i < hwords; i++) {
if(i < len) {
DPORT_REG_WRITE(mem_address + (i * sizeof(word32)), mp->dp[i]);
} else {
DPORT_REG_WRITE(mem_address + (i * sizeof(word32)), 0);
}
}
}
/* return needed hw words. */
/* supported words length */
/* words : {16 , 32, 48, 64, 80, 96, 112, 128} */
/* bits : {512,1024, 1536, 2048, 2560, 3072, 3584, 4096} */
static word32 words2hwords(word32 wd)
{
const word32 shit_ = 4;
return (((wd + 0xf)>>shit_)<<shit_);
}
/* count the number of words is needed for bits */
static word32 bits2words(word32 bits)
{
/* 32 bits */
const word32 d = sizeof(word32) * WOLFSSL_BIT_SIZE;
return((bits + (d - 1))/d);
}
/* get rinv */
static int esp_get_rinv(mp_int *rinv, mp_int *M, word32 exp)
{
int ret = 0;
/* 2^(exp)*/
if((ret = mp_2expt(rinv, exp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate mp_2expt()");
return ret;
}
/* r_inv = R^2 mod M(=P) */
if(ret == 0 && (ret = mp_mod(rinv, M, rinv)) != MP_OKAY){
ESP_LOGE(TAG, "failed to calculate mp_mod()");
return ret;
}
return ret;
}
/* Z = X * Y; */
int esp_mp_mul(fp_int* X, fp_int* Y, fp_int* Z)
{
int ret = 0;
int neg = (X->sign == Y->sign)? MP_ZPOS : MP_NEG;
word32 Xs;
word32 Ys;
word32 Zs;
word32 maxWords_sz;
word32 hwWords_sz;
/* ask bits number */
Xs = mp_count_bits(X);
Ys = mp_count_bits(Y);
Zs = Xs + Ys;
/* maximum bits and words for writing to hw */
maxWords_sz = bits2words(max(Xs, Ys));
hwWords_sz = words2hwords(maxWords_sz);
/* sanity check */
if((hwWords_sz<<5) > ESP_HW_MULTI_RSAMAX_BITS) {
ESP_LOGW(TAG, "exceeds max bit length(2048)");
return -2;
}
/*Steps to use hw in the following order:
* 1. wait until clean hw engine
* 2. Write(2*N/512bits - 1 + 8) to MULT_MODE_REG
* 3. Write X and Y to memory blocks
* need to write data to each memory block only according to the length
* of the number.
* 4. Write 1 to MUL_START_REG
* 5. Wait for the first operation to be done. Poll INTERRUPT_REG until it reads 1.
* (Or until the INTER interrupt is generated.)
* 6. Write 1 to RSA_INTERRUPT_REG to clear the interrupt.
* 7. Read the Z from RSA_Z_MEM
* 8. Write 1 to RSA_INTERUPT_REG to clear the interrupt.
* 9. Release the hw engine
*/
/* lock hw for use */
if((ret = esp_mp_hw_lock()) != MP_OKAY)
return ret;
if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
return ret;
}
/* step.1 (2*N/512) => N/256. 512 bits => 16 words */
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hwWords_sz >> 3) - 1 + 8);
/* step.2 write X, M and r_inv into memory */
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
/* Y(let-extend) */
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + (hwWords_sz<<2), Y, Ys, hwWords_sz);
/* step.3 start process */
process_start(RSA_MULT_START_REG);
/* step.4,5 wait until done */
wait_uitil_done(RSA_INTERRUPT_REG);
/* step.6 read the result form MEM_Z */
esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Zs));
/* step.7 clear and release hw */
esp_mp_hw_unlock();
Z->sign = (Z->used > 0)? neg : MP_ZPOS;
return ret;
}
/* Z = X * Y (mod M) */
int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
{
int ret = 0;
int negcheck = 0;
word32 Xs;
word32 Ys;
word32 Ms;
word32 maxWords_sz;
word32 hwWords_sz;
word32 zwords;
mp_int r_inv;
mp_int tmpZ;
mp_digit mp;
/* neg check */
if(X->sign != Y->sign) {
/* X*Y becomes negative */
negcheck = 1;
}
/* ask bits number */
Xs = mp_count_bits(X);
Ys = mp_count_bits(Y);
Ms = mp_count_bits(M);
/* maximum bits and words for writing to hw */
maxWords_sz = bits2words(max(Xs, max(Ys, Ms)));
zwords = bits2words(min(Ms, Xs + Ys));
hwWords_sz = words2hwords(maxWords_sz);
if((hwWords_sz<<5) > ESP_HW_RSAMAX_BIT) {
ESP_LOGE(TAG, "exceeds hw maximum bits");
return -2;
}
/* calculate r_inv = R^2 mode M
* where: R = b^n, and b = 2^32
* accordingly R^2 = 2^(n*32*2)
*/
ret = mp_init_multi(&tmpZ, &r_inv, NULL, NULL, NULL, NULL);
if(ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz<<6))) != MP_OKAY) {
ESP_LOGE(TAG, "calculate r_inv failed.");
mp_clear(&tmpZ);
mp_clear(&r_inv);
return ret;
}
/* lock hw for use */
if((ret = esp_mp_hw_lock()) != MP_OKAY){
mp_clear(&tmpZ);
mp_clear(&r_inv);
return ret;
}
/* Calculate M' */
if((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate M dash");
mp_clear(&tmpZ);
mp_clear(&r_inv);
return -1;
}
/*Steps to use hw in the following order:
* 1. wait until clean hw engine
* 2. Write(N/512bits - 1) to MULT_MODE_REG
* 3. Write X,M(=G, X, P) to memory blocks
* need to write data to each memory block only according to the length
* of the number.
* 4. Write M' to M_PRIME_REG
* 5. Write 1 to MODEXP_START_REG
* 6. Wait for the first operation to be done. Poll INTERRUPT_REG until it reads 1.
* (Or until the INTER interrupt is generated.)
* 7. Write 1 to RSA_INTERRUPT_REG to clear the interrupt.
* 8. Write Y to RSA_X_MEM
* 9. Write 1 to RSA_MULT_START_REG
* 10. Wait for the second operation to be completed. Poll INTERRUPT_REG until it reads 1.
* 11. Read the Z from RSA_Z_MEM
* 12. Write 1 to RSA_INTERUPT_REG to clear the interrupt.
* 13. Release the hw engine
*/
if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
return ret;
}
/* step.1 512 bits => 16 words */
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hwWords_sz >> 4) - 1);
/* step.2 write X, M and r_inv into memory */
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv),
hwWords_sz);
/* step.3 write M' into memory */
DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
/* step.4 start process */
process_start(RSA_MULT_START_REG);
/* step.5,6 wait until done */
wait_uitil_done(RSA_INTERRUPT_REG);
/* step.7 Y to MEM_X */
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, Y, Ys, hwWords_sz);
/* step.8 start process */
process_start(RSA_MULT_START_REG);
/* step.9,11 wait until done */
wait_uitil_done(RSA_INTERRUPT_REG);
/* step.12 read the result from MEM_Z */
esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, &tmpZ, zwords);
/* step.13 clear and release hw */
esp_mp_hw_unlock();
/* additional steps */
/* this needs for known issue when Z is greater than M */
if(mp_cmp(&tmpZ, M)==FP_GT) {
/* Z -= M */
mp_sub(&tmpZ, M, &tmpZ);
}
if(negcheck) {
mp_sub(M, &tmpZ, &tmpZ);
}
mp_copy(&tmpZ, Z);
mp_clear(&tmpZ);
mp_clear(&r_inv);
return ret;
}
/* Z = X^Y mod M */
int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
{
int ret = 0;
word32 Xs;
word32 Ms;
word32 maxWords_sz;
word32 hwWords_sz;
mp_int r_inv;
mp_digit mp;
/* ask bits number */
Xs = mp_count_bits(X);
Ms = mp_count_bits(M);
/* maximum bits and words for writing to hw */
maxWords_sz = bits2words(max(Xs, max(Ys, Ms)));
hwWords_sz = words2hwords(maxWords_sz);
if((hwWords_sz<<5) > ESP_HW_RSAMAX_BIT) {
ESP_LOGE(TAG, "exceeds hw maximum bits");
return -2;
}
/* calculate r_inv = R^2 mode M
* where: R = b^n, and b = 2^32
* accordingly R^2 = 2^(n*32*2)
*/
ret = mp_init(&r_inv);
if(ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz<<6))) != MP_OKAY) {
ESP_LOGE(TAG, "calculate r_inv failed.");
mp_clear(&r_inv);
return ret;
}
/* lock and init the hw */
if((ret = esp_mp_hw_lock()) != MP_OKAY) {
mp_clear(&r_inv);
return ret;
}
/* calc M' */
/* if Pm is odd, uses mp_montgomery_setup() */
if((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate M dash");
mp_clear(&r_inv);
return -1;
}
/*Steps to use hw in the following order:
* 1. Write(N/512bits - 1) to MODEXP_MODE_REG
* 2. Write X, Y, M and r_inv to memory blocks
* need to write data to each memory block only according to the length
* of the number.
* 3. Write M' to M_PRIME_REG
* 4. Write 1 to MODEXP_START_REG
* 5. Wait for the operation to be done. Poll INTERRUPT_REG until it reads 1.
* (Or until the INTER interrupt is generated.)
* 6. Read the result Z(=Y) from Z_MEM
* 7. Write 1 to INTERRUPT_REG to clear the interrupt.
*/
if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
return ret;
}
/* step.1 */
DPORT_REG_WRITE(RSA_MODEXP_MODE_REG, (hwWords_sz >> 4) - 1);
/* step.2 write G, X, P, r_inv and M' into memory */
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, Y, Ys, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv),
hwWords_sz);
/* step.3 write M' into memory */
DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
/* step.4 start process */
process_start(RSA_START_MODEXP_REG);
/* step.5 wait until done */
wait_uitil_done(RSA_INTERRUPT_REG);
/* step.6 read a result form memory */
esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Ms));
/* step.7 clear and release hw */
esp_mp_hw_unlock();
mp_clear(&r_inv);
return ret;
}
#endif /* !NO_RSA || HAVE_ECC */
#endif /* (WOLFSS_ESP32WROOM32_CRYPT) && (NO_WOLFSSL_ESP32WROOM32_CRYPT_RES_PRI)*/

View file

@ -1,434 +0,0 @@
/* esp32_sha.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <string.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WC_SHA384) || \
defined(WC_SHA512)
#include "wolfssl/wolfcrypt/logging.h"
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
#include <wolfssl/wolfcrypt/sha.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/sha512.h>
#include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
#include "wolfssl/wolfcrypt/error-crypt.h"
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
static const char* TAG = "wolf_hw_sha";
/* continue register offset */
#define CONTINUE_REG_OFFSET (0x04) /* start_reg + 0x04 */
#ifdef NO_SHA
#define WC_SHA_DIGEST_SIZE 20
#endif
/* mutex */
#if defined(SINGLE_THREADED)
static int InUse = 0;
#else
static wolfSSL_Mutex sha_mutex;
static int espsha_CryptHwMutexInit = 0;
#endif
/*
enum SHA_TYPE {
SHA1 = 0,
SHA2_256,
SHA2_384,
SHA2_512,
SHA_INVALID = -1,
};
*/
static word32 esp_sha_digest_size(enum SHA_TYPE type)
{
ESP_LOGV(TAG, "enter esp_sha_digest_size");
switch(type){
#ifndef NO_SHA
case SHA1:
return WC_SHA_DIGEST_SIZE;
#endif
#ifndef NO_SHA256
case SHA2_256:
return WC_SHA256_DIGEST_SIZE;
#endif
#ifdef WOLFSSL_SHA384
case SHA2_384:
return WC_SHA384_DIGEST_SIZE;
#endif
#ifdef WOLFSSL_SHA512
case SHA2_512:
return WC_SHA512_DIGEST_SIZE;
#endif
default:
ESP_LOGE(TAG, "Bad sha type");
return WC_SHA_DIGEST_SIZE;
}
ESP_LOGV(TAG, "leave esp_sha_digest_size");
}
/*
* wait until engines becomes idle
*/
static void esp_wait_until_idle()
{
while((DPORT_REG_READ(SHA_1_BUSY_REG) !=0) ||
(DPORT_REG_READ(SHA_256_BUSY_REG)!=0) ||
(DPORT_REG_READ(SHA_384_BUSY_REG)!=0) ||
(DPORT_REG_READ(SHA_512_BUSY_REG)!=0)){ }
}
/*
* lock hw engine.
* this should be called before using engine.
*/
int esp_sha_try_hw_lock(WC_ESP32SHA* ctx)
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_sha_hw_lock");
/* Init mutex */
#if defined(SINGLE_THREADED)
if(ctx->mode == ESP32_SHA_INIT) {
if(!InUse) {
ctx->mode = ESP32_SHA_HW;
InUse = 1;
} else {
ctx->mode = ESP32_SHA_SW;
}
} else {
/* this should not happens */
ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock.");
return -1;
}
#else
if(espsha_CryptHwMutexInit == 0){
ret = esp_CryptHwMutexInit(&sha_mutex);
if(ret == 0) {
espsha_CryptHwMutexInit = 1;
} else {
ESP_LOGE(TAG, " mutex initialization failed.");
ctx->mode = ESP32_SHA_SW;
return 0;
}
}
/* check if this sha has been operated as sw or hw, or not yet init */
if(ctx->mode == ESP32_SHA_INIT){
/* try to lock the hw engine */
if(esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) {
ctx->mode = ESP32_SHA_HW;
} else {
ESP_LOGI(TAG, "someone used. hw is locked.....");
ESP_LOGI(TAG, "the rest of operation will use sw implementation for this sha");
ctx->mode = ESP32_SHA_SW;
return 0;
}
} else {
/* this should not happens */
ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock.");
return -1;
}
#endif
/* Enable SHA hardware */
periph_module_enable(PERIPH_SHA_MODULE);
ESP_LOGV(TAG, "leave esp_sha_hw_lock");
return ret;
}
/*
* release hw engine
*/
void esp_sha_hw_unlock( void )
{
ESP_LOGV(TAG, "enter esp_sha_hw_unlock");
/* Disable AES hardware */
periph_module_disable(PERIPH_SHA_MODULE);
#if defined(SINGLE_THREADED)
InUse = 0;
#else
/* unlock hw engine for next use */
esp_CryptHwMutexUnLock(&sha_mutex);
#endif
ESP_LOGV(TAG, "leave esp_sha_hw_unlock");
}
/*
* start sha process by using hw engine
*/
static void esp_sha_start_process(WC_ESP32SHA* sha, word32 address)
{
ESP_LOGV(TAG, "enter esp_sha_start_process");
if(sha->isfirstblock){
/* start first message block */
DPORT_REG_WRITE(address, 1);
sha->isfirstblock = 0;
} else {
/* CONTINU_REG */
DPORT_REG_WRITE(address + CONTINUE_REG_OFFSET , 1);
}
ESP_LOGV(TAG, "leave esp_sha_start_process");
}
/*
* process message block
*/
static void esp_process_block(WC_ESP32SHA* ctx, word32 address,
const word32* data, word32 len)
{
int i;
ESP_LOGV(TAG, "enter esp_process_block");
/* check if there are any busy engine */
esp_wait_until_idle();
/* load message data into hw */
for(i=0;i<((len)/(sizeof(word32)));++i){
DPORT_REG_WRITE(SHA_TEXT_BASE+(i*sizeof(word32)),*(data+i));
}
/* notify hw to start process */
esp_sha_start_process(ctx, address);
ESP_LOGV(TAG, "leave esp_process_block");
}
/*
* retrieve sha digest from memory
*/
static void esp_digest_state(WC_ESP32SHA* ctx, byte* hash, enum SHA_TYPE sha_type)
{
/* registers */
word32 SHA_LOAD_REG = SHA_1_LOAD_REG;
word32 SHA_BUSY_REG = SHA_1_BUSY_REG;
ESP_LOGV(TAG, "enter esp_digest_state");
/* sanity check */
if(sha_type == SHA_INVALID) {
ESP_LOGE(TAG, "unexpected error. sha_type is invalid.");
return;
}
SHA_LOAD_REG += (sha_type << 4);
SHA_BUSY_REG += (sha_type << 4);
if(ctx->isfirstblock == 1){
/* no hardware use yet. Nothing to do yet */
return ;
}
/* wait until idle */
esp_wait_until_idle();
/* LOAD final digest */
DPORT_REG_WRITE(SHA_LOAD_REG, 1);
/* wait until done */
while(DPORT_REG_READ(SHA_BUSY_REG) == 1){ }
esp_dport_access_read_buffer((word32*)(hash), SHA_TEXT_BASE,
esp_sha_digest_size(sha_type)/sizeof(word32));
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
if(sha_type==SHA2_384||sha_type==SHA2_512) {
word32 i;
word32* pwrd1 = (word32*)(hash);
/* swap value */
for(i = 0; i <WC_SHA512_DIGEST_SIZE/4; i+=2 ) {
pwrd1[i] ^= pwrd1[i+1];
pwrd1[i+1]^= pwrd1[i];
pwrd1[i] ^= pwrd1[i+1];
}
}
#endif
ESP_LOGV(TAG, "leave esp_digest_state");
}
#ifndef NO_SHA
/*
* sha1 process
*/
int esp_sha_process(struct wc_Sha* sha, const byte* data)
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_sha_process");
word32 SHA_START_REG = SHA_1_START_REG;
esp_process_block(&sha->ctx, SHA_START_REG, (const word32*)data,
WC_SHA_BLOCK_SIZE);
ESP_LOGV(TAG, "leave esp_sha_process");
return ret;
}
/*
* retrieve sha1 digest
*/
int esp_sha_digest_process(struct wc_Sha* sha, byte blockproc)
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_sha_digest_process");
if(blockproc) {
word32 SHA_START_REG = SHA_1_START_REG;
esp_process_block(&sha->ctx, SHA_START_REG, sha->buffer,
WC_SHA_BLOCK_SIZE);
}
esp_digest_state(&sha->ctx, (byte*)sha->digest, SHA1);
ESP_LOGV(TAG, "leave esp_sha_digest_process");
return ret;
}
#endif /* NO_SHA */
#ifndef NO_SHA256
/*
* sha256 process
*/
int esp_sha256_process(struct wc_Sha256* sha, const byte* data)
{
int ret = 0;
word32 SHA_START_REG = SHA_1_START_REG;
ESP_LOGV(TAG, "enter esp_sha256_process");
/* start register offset */
SHA_START_REG += (SHA2_256 << 4);
esp_process_block(&sha->ctx, SHA_START_REG, (const word32*)data,
WC_SHA256_BLOCK_SIZE);
ESP_LOGV(TAG, "leave esp_sha256_process");
return ret;
}
/*
* retrieve sha256 digest
*/
int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockproc)
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_sha256_digest_process");
if(blockproc) {
word32 SHA_START_REG = SHA_1_START_REG + (SHA2_256 << 4);
esp_process_block(&sha->ctx, SHA_START_REG, sha->buffer,
WC_SHA256_BLOCK_SIZE);
}
esp_digest_state(&sha->ctx, (byte*)sha->digest, SHA2_256);
ESP_LOGV(TAG, "leave esp_sha256_digest_process");
return ret;
}
#endif /* NO_SHA256 */
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
/*
* sha512 proess. this is used for sha384 too.
*/
void esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal)
{
enum SHA_TYPE sha_type = sha->ctx.sha_type;
word32 SHA_START_REG = SHA_1_START_REG;
ESP_LOGV(TAG, "enter esp_sha512_block");
/* start register offset */
SHA_START_REG += (sha_type << 4);
if(sha->ctx.mode == ESP32_SHA_SW){
ByteReverseWords64(sha->buffer, sha->buffer,
WC_SHA512_BLOCK_SIZE);
if(isfinal){
sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha->hiLen;
sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha->loLen;
}
} else {
ByteReverseWords((word32*)sha->buffer, (word32*)sha->buffer,
WC_SHA512_BLOCK_SIZE);
if(isfinal){
sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] =
rotlFixed64(sha->hiLen, 32U);
sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] =
rotlFixed64(sha->loLen, 32U);
}
esp_process_block(&sha->ctx, SHA_START_REG, data, WC_SHA512_BLOCK_SIZE);
}
ESP_LOGV(TAG, "leave esp_sha512_block");
}
/*
* sha512 process. this is used for sha384 too.
*/
int esp_sha512_process(struct wc_Sha512* sha)
{
word32 *data = (word32*)sha->buffer;
ESP_LOGV(TAG, "enter esp_sha512_process");
esp_sha512_block(sha, data, 0);
ESP_LOGV(TAG, "leave esp_sha512_process");
return 0;
}
/*
* retrieve sha512 digest. this is used for sha384 too.
*/
int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc)
{
ESP_LOGV(TAG, "enter esp_sha512_digest_process");
if(blockproc) {
word32* data = (word32*)sha->buffer;
esp_sha512_block(sha, data, 1);
}
if(sha->ctx.mode != ESP32_SHA_SW)
esp_digest_state(&sha->ctx, (byte*)sha->digest, sha->ctx.sha_type);
ESP_LOGV(TAG, "leave esp_sha512_digest_process");
return 0;
}
#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */
#endif /* WOLFSSL_ESP32WROOM32_CRYPT */
#endif /* !defined(NO_SHA) ||... */

View file

@ -1,67 +0,0 @@
/* esp32_util.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
(!defined(NO_AES) || !defined(NO_SHA) || !defined(NO_SHA256) ||\
defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512))
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex) {
return wc_InitMutex(mutex);
}
int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t xBlockTime) {
#ifdef SINGLE_THREADED
return wc_LockMutex(mutex);
#else
return ((xSemaphoreTake( *mutex, xBlockTime ) == pdTRUE) ? 0 : BAD_MUTEX_E);
#endif
}
int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) {
return wc_UnLockMutex(mutex);
}
#endif
#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG
#include "esp_timer.h"
#include "esp_log.h"
static uint64_t startTime = 0;
void wc_esp32TimerStart()
{
startTime = esp_timer_get_time();
}
uint64_t wc_esp32elapsedTime()
{
/* return elapsed time since wc_esp32AesTimeStart() is called in us */
return esp_timer_get_time() - startTime;
}
#endif /*WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */

View file

@ -1,176 +0,0 @@
# TSIP FIT Module port
Support for TSIP FIT driver for symmetric AES, SHA1/SHA256 hardware acceleration and TLS-linked capability including Root CA, the server certificate or intermediate certificate verification.
## Overview
Renesas TSIP FIT module with wolfSSL by setting *WOLFSSL_RENESAS_TSIP* definition.
Including the following examples:
* simple tls_client/tls_server
* crypt test
* crypt benchmark
The *user_settings.h* file enables some of the hardened settings.
## Requirements
### 1. [Renesas TSIP FIT module](https://www.renesas.com/us/en/products/software-tools/software-os-middleware-driver/security-crypto/trusted-secure-ip-driver.html)
[FIT module](https://www.renesas.com/us/en/products/software-tools/software-os-middleware-driver/software-package/fit.html)
Note : The included example program is tested with <u>TSIP FIT version **1.06**</u>.
### 2. [e2studio](https://www.renesas.com/us/en/products/software-tools/tools/ide/e2studio.html)
### 3. Evaluation Board that supports TSIP
Note : The included example program is tested with [GR-ROSE](http://gadget.renesas.com/en/product/rose.html), which is classified to RX65N.
## Setup and Build wolfSSL library
1. Uncomment out #define WOLFSSL_RENESAS_TSIP in /path/to/wolfssl/wolfssl/wolfcrypt/settings.h
Uncomment out #define WOLFSSL_RENESAS_RX65N in /path/to/wolfssl/wolfssl/wolfcrypt/settings.h
2. Open a project file at /path/to/wolfssl/IDE/Renesas/e2studio/Projects/wolfssl/ by e2studio and build to create wolfssl library
Note : Generating FIT module source files in advance are required to compile wolfSSL when enabling WOLFSSL_RENESAS_TSIP and WOLFSSL_RENESAS_RX65N. Please see for creating FIT module files at "Setup and Build and example program" in this readme below.
To disable portions of the hardware acceleration you can optionally define:
```
/* Disabled SHA acceleration */
#define NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH
/* Disabled TLS-linked acceleration */
#define NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION
```
### Benchmarks
**Software only implementation:**
*block cipher*
```
RNG 200 KB took 1.099 seconds, 182.000 KB/s
SHA 1 MB took 1.005 seconds, 1.166 MB/s
SHA-256 425 KB took 1.038 seconds, 409.520 KB/s
```
*TLS establishment time*
```
TLS_RSA_WITH_AES_128_CBC_SHA : 0.651 (s)
TLS_RSA_WITH_AES_128_CBC_SHA256 : 0.651 (s)
TLS_RSA_WITH_AES_256_CBC_SHA : 0.642 (s)
TLS_RSA_WITH_AES_256_CBAC_SHA256 : 0.662 (s)
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : 2.050 (s)
```
**Hardware acceleration:**
*block cipher*
```
RNG 1 MB took 1.011 seconds, 1.038 MB/s
SHA 12 MB took 1.001 seconds, 11.515 MB/s
SHA-256 13 MB took 1.001 seconds, 12.900 MB/s
```
*TLS establishment time with TLS-linked capability*
*Perform full TlS-linked capability*
```
TLS_RSA_WITH_AES_128_CBC_SHA : 0.141 (s)
TLS_RSA_WITH_AES_128_CBC_SHA256 : 0.141 (s)
TLS_RSA_WITH_AES_256_CBC_SHA : 0.141 (s)
TLS_RSA_WITH_AES_256_CBAC_SHA256 : 0.144 (s)
```
*Perform certificate verification by TSIP TLS-linked API*
```
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : 1.721 (s)
```
Condition:
Renesas : e2Studio v7.4.0
ToolChain : Renesas CCRX version 3.00.00
TSIP FIT : version 1.0.6
Board : [GR-ROSE](http://gadget.renesas.com/en/product/rose.html)
wolfSSL : 4.1.0
## Setup and Build an example program
An example program expects the following FIT modules:
* r_bsp
* r_cmt_rx
* r_config
* r_ether_rx
* r_sys_time_rx
* r_t4_driver_rx
* r_t4_rx
* r_tsip_rx
These needed source files can be generated by creating a dummy project including Renesas Smart Configurator as steps below:
1. Create a dummy project including Renesas Smart Configurator for your evaluation board type
2. Open Smart Configurator and add FIT modules above
It would need to expand *User Stack Size* property and *Heap Size* of r_bsp.
Change IP ADDRESS and PORT NUMBER in r_t4_rx_config.h
`#define T4_CFG_FIXED_IP_ADDRESS_CH0 192,168,1,33`
`#define T4_CFG_TCP_REPID1_PORT_NUMBER 11111`
Note: It would need to modify other configuration base on evaluation board.
When using GR-ROSE, you can choose "GR-ROSE" from "board" tab and "board" drop-down list and then is able to follow settings below:
Go to component tab and open r_ether_rx properties:
Ethernet interface : RMII
The register bus of PHY0 for ETHER0/1: Use ETHER0
Resource, ETHERC: Check ETHERC0_RMII
Go to component tab and open r_t4_rx properties:
Enable/Disable DHCP function : 0
IP address for ch0, when DHCP disable : 192,168,1,33
TCP REPID1 prot number : 11111
Go to pins tab and select ethernet controller
Check to use pins
3. Generate source code
Now, it is able to copy these FIT modules into an example project.
4. Make "smc_gen" folder under /path/to/wolfssl/IDE/Renesas/e2studio/Projects/test/src/
5. Copy the FIT modules into the folder that is created at step 4.
6. Open an example project file at /path/to/wolfssl/IDE/Renesas/e2studio/Projects/test/ by e2studio
7. Enable a macro definition in /path/to/wolfssl/IDE/Renesas/e2studio/Projects/test/src/wolfssl_demo.h for application type
`#define CRYPT_TEST // enable crypt test`
`#define BENCHMARK // enable benchmark application`
`#define TLS_CLIENT // enable simple tls client application`
`#define TLS_SERVER // enable simple tls server application`
`#define USE_TSIP_TLS // to inform user key and flash keying, when using TSIP`
Note: CRYPT_TEST and BENCHMARK can be enabled at the same time. TLS_CLIENT and TLS_SERVER cannot be enabled together other definitions.
7. Setup debug configuration based on your debug hardware
## Run client/server program on the device
When testing the embedded client or server on the device, it is recommended to test against one of the standard wolfSSL example application running on a desktop machine.
For the embedded client, an example server commands for running on a desktop machine, IP address 192.168.1.45, is as follows:
`$./example/server/server -b -d -i`
For the embedded server, an example client commands for running on a desktop machine is as follows:
`$./example/client/client -h 192.168.1.33 -p 11111`
## Modify an example program
To use own TSIP keys for TSIP TLS-linked API use, it needs own flash keyring, PSS signed signature and RSA key.
### Create flash keyring and use it in an example program
1. Please follow the instruction at TSIP manual, chapter 7. Key Data Operations.
2. Copy and paste s_flash[] data to s_flash[] data in example-program/key_data.c
`const uint32_t s_flash[] =`
### Create RSA key pair for signing Root CA verification and use them in an example program
To use TSIP TLS-linked APIs, it needs RSA key pair and Root CA certificate bundle signature by RSA 2048 PSS with SHA256.
Shell and Perl script program in /path/to/wolfssl/IDE/Renesas/e2studio/Projects/tools/ can be used for the purpose.
* generate_rsa_keypair.sh : generate RSA 2048 bit key pair. Show modulus and public exponent when specifying "-s" option
* rsa_pss_sign.sh : sign the file by the specified private key
* genhexbuf.pl : generate C header file including a byte array generated from the specified file in the script
Modulus and public exponent showed by `generate_rsa_keypair.sh` can be used for input date to Renesas Secure Flash Programmer to generate encrypted RSA keys for TSIP TLS-linked API use. Please follow the instruction about how to generate RSA keys in the TSIP manual.
Generated byte array of signed signature by genhexbuf.pl can be replaced signature data in key_data.c of an example program.
Encrypted RSA key and generated byte array of signed signature need to be informed wolfSSL library before loading CA certification. Please see SetTsipTlskey() function an example program about how to inform them.
### Coding
In your application you must include <wolfssl/wolfcrypt/settings.h> before any other wolfSSL headers. If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own `user_settings.h` file. You can find a good reference for this in `/path/to/Renesas/e2studio/Projects/common/user_settings.h`.
## Support
For question please email [support@wolfssl.com]

View file

@ -1,156 +0,0 @@
/* renesas_tsip_aes.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <string.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <stdio.h>
#ifndef NO_AES
#if defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
!defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_AES)
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/aes.h>
#include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h"
struct Aes;
int wc_tsip_AesCbcEncrypt(struct Aes* aes, byte* out, const byte* in, word32 sz)
{
tsip_aes_handle_t _handle;
word32 ret;
word32 blocks = (sz / AES_BLOCK_SIZE);
uint32_t dataLength;
byte *iv;
if ((in == NULL) || (out == NULL) || (aes == NULL))
return BAD_FUNC_ARG;
/* while doing TLS handshake, TSIP driver keeps true-key and iv *
* on the device. iv is dummy */
iv = (uint8_t*)aes->reg;
if((ret = tsip_hw_lock()) != 0){
WOLFSSL_MSG("Failed to lock");
return ret;
}
if (aes->ctx.keySize == 16) {
ret = R_TSIP_Aes128CbcEncryptInit(&_handle, &aes->ctx.tsip_keyIdx, iv);
} else if (aes->ctx.keySize == 32) {
ret = R_TSIP_Aes256CbcEncryptInit(&_handle, &aes->ctx.tsip_keyIdx, iv);
} else {
tsip_hw_unlock();
return -1;
}
while (ret == TSIP_SUCCESS && blocks--) {
if (aes->ctx.keySize == 16)
ret = R_TSIP_Aes128CbcEncryptUpdate(&_handle, (uint8_t*)in,
(uint8_t*)out, (uint32_t)AES_BLOCK_SIZE);
else
ret = R_TSIP_Aes256CbcEncryptUpdate(&_handle, (uint8_t*)in,
(uint8_t*)out, (uint32_t)AES_BLOCK_SIZE);
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
if (ret == TSIP_SUCCESS) {
if (aes->ctx.keySize == 16) {
ret = R_TSIP_Aes128CbcEncryptFinal(&_handle, out, &dataLength);
} else {
ret = R_TSIP_Aes256CbcEncryptFinal(&_handle, out, &dataLength);
}
} else {
WOLFSSL_MSG("TSIP AES CBC encryption failed");
ret = -1;
}
tsip_hw_unlock();
return ret;
}
int wc_tsip_AesCbcDecrypt(struct Aes* aes, byte* out, const byte* in, word32 sz)
{
tsip_aes_handle_t _handle;
word32 ret;
word32 blocks = (sz / AES_BLOCK_SIZE);
uint32_t dataLength;
byte *iv;
if ((in == NULL) || (out == NULL) || (aes == NULL))
return BAD_FUNC_ARG;
iv = (uint8_t*)aes->reg;
if((ret = tsip_hw_lock()) != 0){
WOLFSSL_MSG("Failed to lock");
return ret;
}
if (aes->ctx.keySize == 16) {
ret = R_TSIP_Aes128CbcDecryptInit(&_handle, &aes->ctx.tsip_keyIdx, iv);
} else if (aes->ctx.keySize == 32) {
ret = R_TSIP_Aes256CbcDecryptInit(&_handle, &aes->ctx.tsip_keyIdx, iv);
} else {
tsip_hw_unlock();
return -1;
}
while (ret == TSIP_SUCCESS && blocks--) {
if (aes->ctx.keySize == 16)
ret = R_TSIP_Aes128CbcDecryptUpdate(&_handle, (uint8_t*)in,
(uint8_t*)out, (uint32_t)AES_BLOCK_SIZE);
else
ret = R_TSIP_Aes256CbcDecryptUpdate(&_handle, (uint8_t*)in,
(uint8_t*)out, (uint32_t)AES_BLOCK_SIZE);
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
if (ret == TSIP_SUCCESS) {
if (aes->ctx.keySize == 16)
ret = R_TSIP_Aes128CbcDecryptFinal(&_handle, out, &dataLength);
else
ret = R_TSIP_Aes256CbcDecryptFinal(&_handle, out, &dataLength);
} else {
WOLFSSL_MSG("TSIP AES CBC decryption failed");
ret = -1;
}
tsip_hw_unlock();
return ret;
}
#endif /* WOLFSSL_RENESAS_TSIP_CRYPT */
#endif /* NO_AES */

View file

@ -1,274 +0,0 @@
/* renesas_tsip_sha.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <string.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if !defined(NO_SHA) || !defined(NO_SHA256)
#include <wolfssl/wolfcrypt/logging.h>
#if defined(WOLFSSL_RENESAS_TSIP_CRYPT)
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h>
#if !defined(NO_SHA)
#include <wolfssl/wolfcrypt/sha.h>
static void TSIPHashFree(wolfssl_TSIP_Hash* hash)
{
if (hash == NULL)
return;
if (hash->msg != NULL) {
XFREE(hash->msg, hash->heap, DYNAMIC_TYPE_TMP_BUFFER);
hash->msg = NULL;
}
}
static int TSIPHashInit(wolfssl_TSIP_Hash* hash, void* heap, int devId,
word32 sha_type)
{
if (hash == NULL) {
return BAD_FUNC_ARG;
}
(void)devId;
XMEMSET(hash, 0, sizeof(wolfssl_TSIP_Hash));
hash->heap = heap;
hash->len = 0;
hash->used = 0;
hash->msg = NULL;
hash->sha_type = sha_type;
return 0;
}
static int TSIPHashUpdate(wolfssl_TSIP_Hash* hash, const byte* data, word32 sz)
{
if (hash == NULL || (sz > 0 && data == NULL)) {
return BAD_FUNC_ARG;
}
if (hash->len < hash->used + sz) {
if (hash->msg == NULL) {
hash->msg = (byte*)XMALLOC(hash->used + sz, hash->heap,
DYNAMIC_TYPE_TMP_BUFFER);
} else {
#ifdef FREERTOS
byte* pt = (byte*)XMALLOC(hash->used + sz, hash->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pt == NULL) {
return MEMORY_E;
}
XMEMCPY(pt, hash->msg, hash->used);
XFREE(hash->msg, hash->heap, DYNAMIC_TYPE_TMP_BUFFER);
hash->msg = NULL;
hash->msg = pt;
#else
byte* pt = (byte*)XREALLOC(hash->msg, hash->used + sz, hash->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pt == NULL) {
return MEMORY_E;
}
hash->msg = pt;
#endif
}
if (hash->msg == NULL) {
return MEMORY_E;
}
hash->len = hash->used + sz;
}
XMEMCPY(hash->msg + hash->used, data , sz);
hash->used += sz;
return 0;
}
static int TSIPHashFinal(wolfssl_TSIP_Hash* hash, byte* out, word32 outSz)
{
int ret;
void* heap;
tsip_sha_md5_handle_t handle;
uint32_t sz;
e_tsip_err_t (*Init)(tsip_sha_md5_handle_t*);
e_tsip_err_t (*Update)(tsip_sha_md5_handle_t*, uint8_t*, uint32_t);
e_tsip_err_t (*Final )(tsip_sha_md5_handle_t*, uint8_t*, uint32_t*);
if (hash == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
if (hash->sha_type == TSIP_SHA1) {
Init = R_TSIP_Sha1Init;
Update = R_TSIP_Sha1Update;
Final = R_TSIP_Sha1Final;
} else if (hash->sha_type == TSIP_SHA256) {
Init = R_TSIP_Sha256Init;
Update = R_TSIP_Sha256Update;
Final = R_TSIP_Sha256Final;
} else
return BAD_FUNC_ARG;
heap = hash->heap;
tsip_hw_lock();
if (Init(&handle) == TSIP_SUCCESS) {
ret = Update(&handle, (uint8_t*)hash->msg, hash->used);
if (ret == TSIP_SUCCESS) {
ret = Final(&handle, out, (uint32_t*)&sz);
if (ret != TSIP_SUCCESS || sz != outSz) {
return ret;
}
}
}
tsip_hw_unlock();
TSIPHashFree(hash);
return TSIPHashInit(hash, heap, 0, hash->sha_type);
}
static int TSIPHashGet(wolfssl_TSIP_Hash* hash, byte* out, word32 outSz)
{
int ret;
tsip_sha_md5_handle_t handle;
uint32_t sz;
e_tsip_err_t (*Init)(tsip_sha_md5_handle_t*);
e_tsip_err_t (*Update)(tsip_sha_md5_handle_t*, uint8_t*, uint32_t);
e_tsip_err_t (*Final )(tsip_sha_md5_handle_t*, uint8_t*, uint32_t*);
if (hash == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
if (hash->sha_type == TSIP_SHA1) {
Init = R_TSIP_Sha1Init;
Update = R_TSIP_Sha1Update;
Final = R_TSIP_Sha1Final;
} else if (hash->sha_type == TSIP_SHA256) {
Init = R_TSIP_Sha256Init;
Update = R_TSIP_Sha256Update;
Final = R_TSIP_Sha256Final;
} else
return BAD_FUNC_ARG;
tsip_hw_lock();
if (Init(&handle) == TSIP_SUCCESS) {
ret = Update(&handle, (uint8_t*)hash->msg, hash->used);
if (ret == TSIP_SUCCESS) {
ret = Final(&handle, out, &sz);
if (ret != TSIP_SUCCESS || sz != outSz) {
return ret;
}
}
}
tsip_hw_unlock();
return 0;
}
static int TSIPHashCopy(wolfssl_TSIP_Hash* src, wolfssl_TSIP_Hash* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
XMEMCPY(dst, src, sizeof(wolfssl_TSIP_Hash));
if (src->len > 0 && src->msg != NULL) {
dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (dst->msg == NULL) {
return MEMORY_E;
}
XMEMCPY(dst->msg, src->msg, src->len);
}
return 0;
}
/* */
int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
{
return TSIPHashInit(sha, heap, devId, TSIP_SHA1);
}
int wc_ShaUpdate(wc_Sha* sha, const byte* in, word32 sz)
{
return TSIPHashUpdate(sha, in, sz);
}
int wc_ShaFinal(wc_Sha* sha, byte* hash)
{
return TSIPHashFinal(sha, hash, WC_SHA_DIGEST_SIZE);
}
int wc_ShaGetHash(wc_Sha* sha, byte* hash)
{
return TSIPHashGet(sha, hash, WC_SHA_DIGEST_SIZE);
}
int wc_ShaCopy(wc_Sha256* src, wc_Sha256* dst)
{
return TSIPHashCopy(src, dst);
}
#endif /* !NO_SHA */
#if !defined(NO_SHA256)
#include <wolfssl/wolfcrypt/sha256.h>
/* */
int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
{
return TSIPHashInit(sha, heap, devId, TSIP_SHA256);
}
int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz)
{
return TSIPHashUpdate(sha, in, sz);
}
int wc_Sha256Final(wc_Sha256* sha, byte* hash)
{
return TSIPHashFinal(sha, hash, WC_SHA256_DIGEST_SIZE);
}
int wc_Sha256GetHash(wc_Sha256* sha, byte* hash)
{
return TSIPHashGet(sha, hash, WC_SHA256_DIGEST_SIZE);
}
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
{
return TSIPHashCopy(src, dst);
}
#endif /* !NO_SHA256 */
#endif /* WOLFSSL_RENESAS_TSIP_CRYPT */
#endif /* #if !defined(NO_SHA) || !defined(NO_SHA256) */

View file

@ -1,719 +0,0 @@
/* renesas_tsip_util.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_RENESAS_TSIP)
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h>
#include <wolfssl/wolfcrypt/memory.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/ssl.h>
#include <wolfssl/internal.h>
#include <stdio.h>
/* mutex */
wolfSSL_Mutex tsip_mutex;
static int tsip_CryptHwMutexInit_ = 0;
/* ./ca-cert.der.sign, */
/* expect to have these variables defined at user application */
extern uint32_t s_flash[];
extern uint32_t s_inst1[R_TSIP_SINST_WORD_SIZE];
extern uint32_t s_inst2[R_TSIP_SINST2_WORD_SIZE];
static const byte *ca_cert_sig;
/* user key */
static tsip_key_data g_user_key_info;
/* tsip only keep one encrypted ca public key */
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
static uint32_t g_encrypted_publicCA_key[R_TSIP_SINST_WORD_SIZE];
static uint32_t g_CAscm_Idx; /* index of CM table */
#endif
static int tsip_CryptHwMutexInit(wolfSSL_Mutex* mutex) {
return wc_InitMutex(mutex);
}
static int tsip_CryptHwMutexLock(wolfSSL_Mutex* mutex) {
return wc_LockMutex(mutex);
}
static int tsip_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) {
return wc_UnLockMutex(mutex);
}
/*
* lock hw engine.
* this should be called before using engine.
*/
int tsip_hw_lock()
{
int ret = 0;
WOLFSSL_MSG("enter esp_sha_hw_lock");
if(tsip_CryptHwMutexInit_ == 0){
ret = tsip_CryptHwMutexInit(&tsip_mutex);
if(ret == 0) {
tsip_CryptHwMutexInit_ = 1;
} else {
WOLFSSL_MSG(" mutex initialization failed.");
return -1;
}
}
if(tsip_CryptHwMutexLock(&tsip_mutex) != 0) {
/* this should not happens */
return -1;
}
WOLFSSL_MSG("leave tsip_sha_try_hw_lock");
return ret;
}
/*
* release hw engine
*/
void tsip_hw_unlock( void )
{
WOLFSSL_MSG("enter tsip_hw_unlock");
/* unlock hw engine for next use */
tsip_CryptHwMutexUnLock(&tsip_mutex);
WOLFSSL_MSG("leave tsip_hw_unlock");
}
/* check if tsip tls functions can be used for the cipher */
/* cipher0 : in the some cipher suite, */
/* first byte becomes greater than 0, otherwise 0x00 */
/* side : CLIENT END or SEVER END */
int tsip_useable(const struct WOLFSSL *ssl)
{
byte cipher0;
byte cipher;
byte side;
/* sanity check */
if (ssl == NULL)
return BAD_FUNC_ARG;
/* when rsa key index == NULL, tsip isn't used for cert verification. */
/* in the case, we cannot use TSIP. */
if (!ssl->peerTsipEncRsaKeyIndex)
return 0;
/* when enabled Extended Master Secret, we cannot use TSIP. */
if (ssl->options.haveEMS)
return 0;
cipher0 = ssl->options.cipherSuite0;
cipher = ssl->options.cipherSuite;
side = ssl->options.side;
if (cipher0 > 0x00)
return 0;
if ((cipher == l_TLS_RSA_WITH_AES_128_CBC_SHA ||
cipher == l_TLS_RSA_WITH_AES_128_CBC_SHA256 ||
cipher == l_TLS_RSA_WITH_AES_256_CBC_SHA ||
cipher == l_TLS_RSA_WITH_AES_256_CBC_SHA256) &&
side == WOLFSSL_CLIENT_END)
return 1;
else
return 0;
}
/* check if the g_alreadyVerified CA's key can be used for *
* peer's certification */
byte tsip_checkCA(word32 cmIdx)
{
return (cmIdx == g_CAscm_Idx? 1:0);
}
/* check if the root CA has been verified by TSIP, *
* and it exists in the CM table. */
byte tsip_rootCAverified( )
{
return (g_CAscm_Idx != (uint32_t)-1 ? 1:0);
}
/* open TSIP driver for use */
int tsip_Open( ) {
int ret;
if ((ret = tsip_hw_lock()) == 0) {
/* open the TSIP */
ret = R_TSIP_Open((uint32_t*)s_flash, s_inst1, s_inst2);
if( ret != TSIP_SUCCESS ) {
WOLFSSL_MSG("RENESAS TSIP Open failed");
}
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
/* generate TLS Rsa public key for Certificate verification */
if (ret == TSIP_SUCCESS && g_user_key_info.encrypted_user_tls_key) {
ret = R_TSIP_GenerateTlsRsaPublicKeyIndex(
g_user_key_info.encrypted_session_key,
g_user_key_info.iv,
g_user_key_info.encrypted_user_tls_key,
&g_user_key_info.user_rsa2048_tls_pubindex);
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG("R_TSIP_GenerateTlsRsaPublicKeyIndex failed");
} else {
/* close once */
tsip_Close( );
/* open again with s_inst[] */
XMEMCPY(s_inst1,
g_user_key_info.user_rsa2048_tls_pubindex.value,
sizeof(s_inst1));
ret = R_TSIP_Open((uint32_t*)s_flash, s_inst1, s_inst2);
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG("R_TSIP_(Re)Open failed");
}
/* init vars */
g_CAscm_Idx = (uint32_t)-1;
}
}
#endif
/* unlock hw */
tsip_hw_unlock();
} else
WOLFSSL_MSG("Failed to lock tsip hw \n");
return ret;
}
/* close TSIP driver */
void tsip_Close( ) {
int ret;
if ((ret = tsip_hw_lock()) == 0) {
/* close TSIP */
ret = R_TSIP_Close();
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
g_CAscm_Idx = (uint32_t)-1;
#endif
/* unlock hw */
tsip_hw_unlock();
if( ret != TSIP_SUCCESS ) {
WOLFSSL_MSG("RENESAS TSIP Close failed");
}
} else
WOLFSSL_MSG("Failed to unlock tsip hw \n");
}
/* Support functions for TSIP TLS Capability */
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
/* to inform ca certificate sign */
/* signature format expects RSA 2048 PSS with SHA256 */
void tsip_inform_cert_sign(const byte *sign)
{
if(sign)
ca_cert_sig = sign;
}
/* inform user key */
/* the function expects to be called from user application */
/* user has to create these key information by Renesas tool in advance.*/
void tsip_inform_user_keys(
byte *encrypted_session_key,
byte *iv,
byte *encrypted_user_tls_key
)
{
g_user_key_info.encrypted_session_key = NULL;
g_user_key_info.iv = NULL;
g_user_key_info.encrypted_user_tls_key = NULL;
if ( encrypted_session_key ) {
g_user_key_info.encrypted_session_key = encrypted_session_key;
}
if ( iv ) {
g_user_key_info.iv = iv;
}
if ( encrypted_user_tls_key ) {
g_user_key_info.encrypted_user_tls_key = encrypted_user_tls_key;
}
}
#ifndef NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION
/* convert def to tsip define */
static byte _tls2tsipdef(byte cipher)
{
byte def = R_TSIP_TLS_RSA_WITH_AES_128_CBC_SHA;
switch(cipher){
case l_TLS_RSA_WITH_AES_128_CBC_SHA:
break;
case l_TLS_RSA_WITH_AES_128_CBC_SHA256:
def = R_TSIP_TLS_RSA_WITH_AES_128_CBC_SHA256;
break;
case l_TLS_RSA_WITH_AES_256_CBC_SHA:
def = R_TSIP_TLS_RSA_WITH_AES_256_CBC_SHA;
break;
case l_TLS_RSA_WITH_AES_256_CBC_SHA256:
def = R_TSIP_TLS_RSA_WITH_AES_256_CBC_SHA256;
break;
default:break;
}
return def;
}
/* Sha1Hmac */
int tsip_Sha1Hmac(const struct WOLFSSL *ssl, const byte *myInner,
word32 innerSz, const byte *in, word32 sz, byte *digest,
word32 verify)
{
tsip_hmac_sha_handle_t _handle;
tsip_hmac_sha_key_index_t key_index;
int ret;
if ((ssl == NULL) || (myInner == NULL) || (in == NULL) ||
(digest == NULL))
return BAD_FUNC_ARG;
if ((ret = tsip_hw_lock()) != 0) {
WOLFSSL_MSG("hw lock failed\n");
return ret;
}
if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) ||
(ssl->options.side == WOLFSSL_SERVER_END && verify) )
XMEMCPY(key_index.value, ssl->keys.tsip_client_write_MAC_secret,
sizeof(key_index.value));
else
XMEMCPY(key_index.value, ssl->keys.tsip_server_write_MAC_secret,
sizeof(key_index.value));
ret = R_TSIP_Sha1HmacGenerateInit(&_handle, &key_index);
if (ret == TSIP_SUCCESS)
ret = R_TSIP_Sha1HmacGenerateUpdate(&_handle, (uint8_t*)myInner,
(uint32_t)innerSz);
if (ret == TSIP_SUCCESS)
ret = R_TSIP_Sha1HmacGenerateUpdate(&_handle, (uint8_t*)in, sz);
if (ret == TSIP_SUCCESS)
ret = R_TSIP_Sha1HmacGenerateFinal(&_handle, digest);
/* unlock hw */
tsip_hw_unlock();
return ret;
}
/* Sha256Hmac */
int tsip_Sha256Hmac(const struct WOLFSSL *ssl, const byte *myInner,
word32 innerSz, const byte *in, word32 sz, byte *digest,
word32 verify)
{
tsip_hmac_sha_handle_t _handle;
tsip_hmac_sha_key_index_t key_index;
int ret;
if ((ssl == NULL) || (myInner == NULL) || (in == NULL) ||
(digest == NULL))
return BAD_FUNC_ARG;
if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) ||
(ssl->options.side == WOLFSSL_SERVER_END && verify) )
XMEMCPY(key_index.value, ssl->keys.tsip_client_write_MAC_secret,
sizeof(key_index.value));
else
XMEMCPY(key_index.value, ssl->keys.tsip_server_write_MAC_secret,
sizeof(key_index.value));
if ((ret = tsip_hw_lock()) != 0) {
WOLFSSL_MSG("hw lock failed\n");
return ret;
}
ret = R_TSIP_Sha256HmacGenerateInit(&_handle, &key_index);
if (ret == TSIP_SUCCESS)
ret = R_TSIP_Sha256HmacGenerateUpdate(&_handle, (uint8_t*)myInner,
innerSz);
if (ret == TSIP_SUCCESS)
ret = R_TSIP_Sha256HmacGenerateUpdate(&_handle, (uint8_t*)in, sz);
if (ret == TSIP_SUCCESS)
ret = R_TSIP_Sha256HmacGenerateFinal(&_handle, digest);
/* unlock hw */
tsip_hw_unlock();
return ret;
}
/* generate Verify Data based on master secret */
int tsip_generateVerifyData(const byte *ms, /* master secret */
const byte *side, const byte *handshake_hash,
byte *hashes /* out */)
{
int ret ;
uint32_t l_side = R_TSIP_TLS_GENERATE_CLIENT_VERIFY;
if ((ms == NULL) || (side == NULL) || (handshake_hash == NULL) ||
(hashes == NULL))
return BAD_FUNC_ARG;
if (XSTRNCMP((const char*)side, (const char*)tls_server, FINISHED_LABEL_SZ)
== 0)
{
l_side = R_TSIP_TLS_GENERATE_SERVER_VERIFY;
}
if ((ret = tsip_hw_lock()) == 0) {
ret = R_TSIP_TlsGenerateVerifyData(l_side, (uint32_t*)ms,
(uint8_t*)handshake_hash, hashes/* out */);
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG("R_TSIP_TlsGenerateSessionKey failed\n");
}
}
/* unlock hw */
tsip_hw_unlock();
return ret;
}
/* generate keys for TLS communication */
int tsip_generateSeesionKey(struct WOLFSSL *ssl)
{
int ret;
Ciphers *enc;
Ciphers *dec;
tsip_hmac_sha_key_index_t key_client_mac;
tsip_hmac_sha_key_index_t key_server_mac;
tsip_aes_key_index_t key_client_aes;
tsip_aes_key_index_t key_server_aes;
if (ssl== NULL)
return BAD_FUNC_ARG;
if ((ret = tsip_hw_lock()) == 0) {
ret = R_TSIP_TlsGenerateSessionKey(
_tls2tsipdef(ssl->options.cipherSuite),
(uint32_t*)ssl->arrays->tsip_masterSecret,
(uint8_t*)ssl->arrays->clientRandom,
(uint8_t*)ssl->arrays->serverRandom, &key_client_mac,
&key_server_mac, &key_client_aes, &key_server_aes,
NULL, NULL);
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG("R_TSIP_TlsGenerateSessionKey failed\n");
} else {
/* succeeded creating session keys */
/* alloc aes instance for both enc and dec */
enc = &ssl->encrypt;
dec = &ssl->decrypt;
if (enc) {
if (enc->aes == NULL) {
enc->aes = (Aes*)XMALLOC(sizeof(Aes), ssl->heap,
DYNAMIC_TYPE_CIPHER);
if (enc->aes == NULL)
return MEMORY_E;
}
XMEMSET(enc->aes, 0, sizeof(Aes));
}
if (dec) {
if (dec->aes == NULL) {
dec->aes = (Aes*)XMALLOC(sizeof(Aes), ssl->heap,
DYNAMIC_TYPE_CIPHER);
if (dec->aes == NULL) {
if (enc) {
XFREE(enc->aes, NULL, DYNAMIC_TYPE_CIPHER);
}
return MEMORY_E;
}
}
XMEMSET(dec->aes, 0, sizeof(Aes));
}
/* copy key index into aes */
if (ssl->options.side == PROVISION_CLIENT) {
XMEMCPY(&enc->aes->ctx.tsip_keyIdx, &key_client_aes,
sizeof(key_client_aes));
XMEMCPY(&dec->aes->ctx.tsip_keyIdx, &key_server_aes,
sizeof(key_server_aes));
} else {
XMEMCPY(&enc->aes->ctx.tsip_keyIdx, &key_server_aes,
sizeof(key_server_aes));
XMEMCPY(&dec->aes->ctx.tsip_keyIdx, &key_client_aes,
sizeof(key_client_aes));
}
/* copy hac key index into keys */
XMEMCPY(ssl->keys.tsip_client_write_MAC_secret, key_client_mac.value,
sizeof(key_client_mac.value));
XMEMCPY(ssl->keys.tsip_server_write_MAC_secret, key_server_mac.value,
sizeof(key_client_mac.value));
/* set up key size and marked readly */
if (enc){
enc->aes->ctx.keySize = ssl->specs.key_size;
/* ready for use */
enc->setup = 1;
}
/* set up key size and marked readly */
if (dec) {
dec->aes->ctx.keySize = ssl->specs.key_size;
/* ready for use */
dec->setup = 1;
}
}
/* unlock hw */
tsip_hw_unlock();
} else
WOLFSSL_MSG("hw lock failed\n");
return ret;
}
/* generate Master secrete by TSIP */
int tsip_generateMasterSecret(const byte *pr, /* pre-master */
const byte *cr, /* client random */
const byte *sr, /* server random */
byte *ms)
{
int ret;
if ((pr == NULL) || (cr == NULL) || (sr == NULL) ||
(ms == NULL))
return BAD_FUNC_ARG;
if ((ret = tsip_hw_lock()) == 0) {
ret = R_TSIP_TlsGenerateMasterSecret( (uint32_t*)pr,
(uint8_t*)cr, (uint8_t*)sr, (uint32_t*)ms);
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG("R_TSIP_TlsGenerateMasterSecret failed\n");
}
/* unlock hw */
tsip_hw_unlock();
} else {
WOLFSSL_MSG(" hw lock failed ");
}
return ret;
}
/* generate pre-Master secrete by TSIP */
int tsip_generatePremasterSecret(byte *premaster, word32 preSz )
{
int ret;
if (premaster == NULL)
return BAD_FUNC_ARG;
if ((ret = tsip_hw_lock()) == 0 && preSz >=
(R_TSIP_TLS_MASTER_SECRET_WORD_SIZE*4)) {
/* generate pre-master, 80 bytes */
ret = R_TSIP_TlsGeneratePreMasterSecret( (uint32_t*)premaster );
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG(" R_TSIP_TlsGeneratePreMasterSecret failed\n");
}
/* unlock hw */
tsip_hw_unlock();
} else {
WOLFSSL_MSG(" hw lock failed or preSz is smaller than 80");
}
return ret;
}
/* generate encrypted pre-Master secrete by TSIP */
int tsip_generateEncryptPreMasterSecret(WOLFSSL *ssl, byte *out, word32 *outSz)
{
int ret;
if ((ssl == NULL) || (out == NULL) || (outSz == NULL))
return BAD_FUNC_ARG;
if ((ret = tsip_hw_lock()) == 0) {
if (*outSz >= 256)
ret = R_TSIP_TlsEncryptPreMasterSecret(
(uint32_t*)ssl->peerTsipEncRsaKeyIndex,
(uint32_t*)&ssl->arrays->preMasterSecret[VERSION_SZ],
(uint8_t*)out);
else
ret = -1;
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG(" R_TSIP_TlsEncryptPreMasterSecret failed\n");
} else {
*outSz = 256; /* TSIP can only handles 2048 RSA */
}
/* unlock hw */
tsip_hw_unlock();
} else {
WOLFSSL_MSG(" hw lock failed ");
}
return ret;
}
#endif /* NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION */
/* Certificate verification by TSIP */
int tsip_tls_CertVerify(const byte *cert, word32 certSz,
const byte *signature, word32 sigSz,
word32 key_n_start, word32 key_n_len,
word32 key_e_start, word32 key_e_len,
byte *tsip_encRsaKeyIndex)
{
int ret;
if (cert == NULL)
return BAD_FUNC_ARG;
if (!signature) {
WOLFSSL_MSG(" signature for ca verification is not set\n");
return -1;
}
if (!tsip_encRsaKeyIndex) {
WOLFSSL_MSG(" tsip_encRsaKeyIndex is NULL.\n");
return -1;
}
if ((ret = tsip_hw_lock()) == 0) {
ret = R_TSIP_TlsCertificateVerification(
(uint32_t*)g_encrypted_publicCA_key,/* encrypted public key */
(uint8_t*)cert, /* certificate der */
certSz, /* length of der */
(uint8_t*)signature, /* sign data by RSA PSS */
key_n_start, /* start position of public key n in bytes */
(key_n_start + key_n_len), /* length of the public key n */
key_e_start, /* start pos, key e in bytes */
(key_e_start + key_e_len), /* length of the public key e */
(uint32_t*)tsip_encRsaKeyIndex /* returned encrypted key */
);
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG(" R_TSIP_TlsCertificateVerification() failed");
}
tsip_hw_unlock();
} else {
WOLFSSL_MSG(" hw lock failed ");
}
return ret;
}
/* Root Certificate verification */
int tsip_tls_RootCertVerify(const byte *cert, word32 cert_len,
word32 key_n_start, word32 key_n_len,
word32 key_e_start, word32 key_e_len,
word32 cm_row)
{
int ret;
/* call to generate encrypted public key for certificate verification */
uint8_t *signature = (uint8_t*)ca_cert_sig;
if (cert == NULL)
return BAD_FUNC_ARG;
if (!signature) {
WOLFSSL_MSG(" signature for ca verification is not set\n");
return -1;
}
if ((ret = tsip_hw_lock()) == 0) {
ret = R_TSIP_TlsRootCertificateVerification(
/* CA cert */
(uint8_t*)cert,
/* length of CA cert */
(uint32_t)cert_len,
/* Byte position of public key */
key_n_start,
(key_n_start + key_n_len),
key_e_start,
(key_e_start + key_e_len),
/* signature by "RSA 2048 PSS with SHA256" */
(uint8_t*)ca_cert_sig,
/* RSA-2048 public key used by
RSA-2048 PSS with SHA256. 560 Bytes*/
g_encrypted_publicCA_key
);
if (ret != TSIP_SUCCESS) {
WOLFSSL_MSG(" R_TSIP_TlsRootCertVerify() failed");
} else {
g_CAscm_Idx = cm_row;
}
tsip_hw_unlock();
} else {
WOLFSSL_MSG(" hw lock failed ");
}
return ret;
}
#endif /* WOLFSSL_RENESAS_TSIP_TLS */
#ifdef WOLFSSL_RENESAS_TSIP_CRYPT_DEBUG
/* err
* e_tsip_err
TSIP_SUCCESS = 0,
TSIP_ERR_SELF_CHECK1, // Self-check 1 fail or TSIP function internal err.
TSIP_ERR_RESOURCE_CONFLICT, // A resource conflict occurred.
TSIP_ERR_SELF_CHECK2, // Self-check 2 fail.
TSIP_ERR_KEY_SET, // setting the invalid key.
TSIP_ERR_AUTHENTICATION, // Authentication failed.
TSIP_ERR_CALLBACK_UNREGIST, // Callback function is not registered.
TSIP_ERR_PARAMETER, // Illegal Input data.
TSIP_ERR_PROHIBIT_FUNCTION, // An invalid function call occurred.
* TSIP_RESUME_FIRMWARE_GENERATE_MAC,
// There is a continuation of R_TSIP_GenerateFirmwareMAC.
*/
static void hexdump(const uint8_t* in, uint32_t len)
{
uint32_t i;
if (in == NULL)
return;
for (i = 0; i <= len;i++, in++){
printf("%02x:", *in);
if (((i+1)%16)==0){
printf("\n");
}
}
printf("\n");
}
byte *ret2err(word32 ret)
{
switch(ret){
case TSIP_SUCCESS: return "success";
case TSIP_ERR_SELF_CHECK1: return "selfcheck1";
case TSIP_ERR_RESOURCE_CONFLICT: return "rsconflict";
case TSIP_ERR_SELF_CHECK2: return "selfcheck2";
case TSIP_ERR_KEY_SET: return "keyset";
case TSIP_ERR_AUTHENTICATION: return "authentication";
case TSIP_ERR_CALLBACK_UNREGIST: return "callback unreg";
case TSIP_ERR_PARAMETER: return "badarg";
case TSIP_ERR_PROHIBIT_FUNCTION: return "prohibitfunc";
case TSIP_RESUME_FIRMWARE_GENERATE_MAC: return "conti-generate-mac";
default:return "unknown";
}
}
#endif /* WOLFSSL_RENESAS_TSIP_CRYPT_DEBUG */
#endif /* WOLFSSL_RENESAS_TSIP */

View file

@ -1,900 +0,0 @@
/* afalg_aes.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#if !defined(NO_AES) && (defined(WOLFSSL_AFALG) || \
defined(WOLFSSL_AFALG_XILINX_AES))
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
#include <sys/uio.h> /* for readv */
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifdef WOLFSSL_AFALG_XILINX_AES
#define WOLFSSL_XILINX_ALIGN sizeof(wolfssl_word)
#endif
static const char WC_TYPE_SYMKEY[] = "skcipher";
static int wc_AesSetup(Aes* aes, const char* type, const char* name, int ivSz, int aadSz)
{
#ifdef WOLFSSL_AFALG_XILINX_AES
byte* key = (byte*)aes->msgBuf;
#else
byte* key = (byte*)aes->key;
#endif
aes->rdFd = wc_Afalg_CreateRead(aes->alFd, type, name);
if (aes->rdFd < 0) {
WOLFSSL_MSG("Unable to accept and get AF_ALG read socket");
aes->rdFd = WC_SOCK_NOTSET;
return aes->rdFd;
}
if (setsockopt(aes->alFd, SOL_ALG, ALG_SET_KEY, key, aes->keylen) != 0) {
WOLFSSL_MSG("Unable to set AF_ALG key");
aes->rdFd = WC_SOCK_NOTSET;
return WC_AFALG_SOCK_E;
}
ForceZero(key, sizeof(aes->key));
/* set up CMSG headers */
XMEMSET((byte*)&(aes->msg), 0, sizeof(struct msghdr));
aes->msg.msg_control = key; /* use existing key buffer for
* control buffer */
#ifdef WOLFSSL_AFALG_XILINX_AES
aes->msg.msg_controllen = CMSG_SPACE(4) +
CMSG_SPACE(sizeof(struct af_alg_iv) + ivSz);
(void)aadSz;
#else
aes->msg.msg_controllen = CMSG_SPACE(4);
if (aadSz > 0) {
aes->msg.msg_controllen += CMSG_SPACE(4);
}
if (ivSz > 0) {
aes->msg.msg_controllen += CMSG_SPACE((sizeof(struct af_alg_iv) + ivSz));
}
#endif
if (wc_Afalg_SetOp(CMSG_FIRSTHDR(&(aes->msg)), aes->dir) < 0) {
WOLFSSL_MSG("Error with setting AF_ALG operation");
aes->rdFd = WC_SOCK_NOTSET;
return -1;
}
return 0;
}
#ifdef WOLFSSL_AFALG
int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
const byte* iv, int dir)
{
#if defined(AES_MAX_KEY_SIZE)
const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
#endif
if (aes == NULL ||
!((keylen == 16) || (keylen == 24) || (keylen == 32))) {
return BAD_FUNC_ARG;
}
#if defined(AES_MAX_KEY_SIZE)
/* Check key length */
if (keylen > max_key_len) {
return BAD_FUNC_ARG;
}
#endif
aes->keylen = keylen;
aes->rounds = keylen/4 + 6;
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif
aes->rdFd = WC_SOCK_NOTSET;
aes->alFd = wc_Afalg_Socket();
if (aes->alFd < 0) {
WOLFSSL_MSG("Unable to open an AF_ALG socket");
return WC_AFALG_SOCK_E;
}
/* save key until type is known i.e. CBC, ECB, ... */
XMEMCPY((byte*)(aes->key), userKey, keylen);
aes->dir = dir;
return wc_AesSetIV(aes, iv);
}
#endif
/* AES-CBC */
#if defined(HAVE_AES_CBC) && defined(WOLFSSL_AFALG)
static const char WC_NAME_AESCBC[] = "cbc(aes)";
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct cmsghdr* cmsg;
struct iovec iov;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCBC,
AES_IV_SIZE, 0)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
}
sz = sz - (sz % AES_BLOCK_SIZE);
if ((sz / AES_BLOCK_SIZE) > 0) {
/* update IV */
cmsg = CMSG_FIRSTHDR(&(aes->msg));
ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg),
(byte*)(aes->reg), AES_IV_SIZE);
if (ret < 0) {
WOLFSSL_MSG("Error setting IV");
return ret;
}
/* set data to be encrypted */
iov.iov_base = (byte*)in;
iov.iov_len = sz;
aes->msg.msg_iov = &iov;
aes->msg.msg_iovlen = 1; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
ret = (int)read(aes->rdFd, out, sz);
if (ret < 0) {
return ret;
}
/* set IV for next CBC call */
XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
}
return 0;
}
#ifdef HAVE_AES_DECRYPT
int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct cmsghdr* cmsg;
struct iovec iov;
int ret;
if (aes == NULL || out == NULL || in == NULL
|| sz % AES_BLOCK_SIZE != 0) {
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCBC,
AES_IV_SIZE, 0)) != 0) {
return ret;
}
}
if ((sz / AES_BLOCK_SIZE) > 0) {
/* update IV */
cmsg = CMSG_FIRSTHDR(&(aes->msg));
ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg),
(byte*)(aes->reg), AES_IV_SIZE);
if (ret != 0) {
return ret;
}
/* set data to be decrypted */
iov.iov_base = (byte*)in;
iov.iov_len = sz;
aes->msg.msg_iov = &iov;
aes->msg.msg_iovlen = 1; /* # of iov structures */
/* set IV for next CBC call */
XMEMCPY(aes->reg, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
ret = (int)read(aes->rdFd, out, sz);
if (ret < 0) {
return ret;
}
}
return 0;
}
#endif
#endif /* HAVE_AES_CBC */
/* AES-DIRECT */
#if (defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AES_ECB)) && \
defined(WOLFSSL_AFALG)
static const char WC_NAME_AESECB[] = "ecb(aes)";
/* common code between ECB encrypt and decrypt
* returns 0 on success */
static int wc_Afalg_AesDirect(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct iovec iov;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESECB,
0, 0)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
}
/* set data to be encrypted */
iov.iov_base = (byte*)in;
iov.iov_len = sz;
aes->msg.msg_iov = &iov;
aes->msg.msg_iovlen = 1; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
ret = (int)read(aes->rdFd, out, sz);
if (ret < 0) {
return ret;
}
return 0;
}
#endif
#if defined(WOLFSSL_AES_DIRECT) && defined(WOLFSSL_AFALG)
void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
{
if (wc_Afalg_AesDirect(aes, out, in, AES_BLOCK_SIZE) != 0) {
WOLFSSL_MSG("Error with AES encrypt direct call");
}
}
void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
{
if (wc_Afalg_AesDirect(aes, out, in, AES_BLOCK_SIZE) != 0) {
WOLFSSL_MSG("Error with AES decrypt direct call");
}
}
int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
const byte* iv, int dir)
{
return wc_AesSetKey(aes, userKey, keylen, iv, dir);
}
#endif
/* AES-CTR */
#if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AFALG)
static const char WC_NAME_AESCTR[] = "ctr(aes)";
/* Increment AES counter */
static WC_INLINE void IncrementAesCounter(byte* inOutCtr)
{
/* in network byte order so start at end and work back */
int i;
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
if (++inOutCtr[i]) /* we're done unless we overflow */
return;
}
}
int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct cmsghdr* cmsg;
struct iovec iov[2];
int ret;
byte* tmp;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
/* consume any unused bytes left in aes->tmp */
tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
while (aes->left && sz) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
sz--;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
if ((ret = wc_AesSetup(aes, WC_TYPE_SYMKEY, WC_NAME_AESCTR,
AES_IV_SIZE, 0)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
}
if (sz > 0) {
aes->left = sz % AES_BLOCK_SIZE;
/* clear previously leftover data */
tmp = (byte*)aes->tmp;
XMEMSET(tmp, 0, AES_BLOCK_SIZE);
/* update IV */
cmsg = CMSG_FIRSTHDR(&(aes->msg));
ret = wc_Afalg_SetIv(CMSG_NXTHDR(&(aes->msg), cmsg),
(byte*)(aes->reg), AES_IV_SIZE);
if (ret < 0) {
WOLFSSL_MSG("Error setting IV");
return ret;
}
/* set data to be encrypted */
iov[0].iov_base = (byte*)in;
iov[0].iov_len = sz - aes->left;
iov[1].iov_base = tmp;
if (aes->left > 0) {
XMEMCPY(tmp, in + sz - aes->left, aes->left);
iov[1].iov_len = AES_BLOCK_SIZE;
}
else {
iov[1].iov_len = 0;
}
aes->msg.msg_iov = iov;
aes->msg.msg_iovlen = 2; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
/* set buffers to hold result and left over stream */
iov[0].iov_base = (byte*)out;
iov[0].iov_len = sz - aes->left;
iov[1].iov_base = tmp;
if (aes->left > 0) {
iov[1].iov_len = AES_BLOCK_SIZE;
}
else {
iov[1].iov_len = 0;
}
ret = (int)readv(aes->rdFd, iov, 2);
if (ret < 0) {
return ret;
}
if (aes->left > 0) {
XMEMCPY(out + sz - aes->left, tmp, aes->left);
aes->left = AES_BLOCK_SIZE - aes->left;
}
}
/* adjust counter after call to hardware */
while (sz >= AES_BLOCK_SIZE) {
IncrementAesCounter((byte*)aes->reg);
sz -= AES_BLOCK_SIZE;
}
if (aes->left > 0) {
IncrementAesCounter((byte*)aes->reg);
}
return 0;
}
#endif /* WOLFSSL_AES_COUNTER */
#ifdef HAVE_AESGCM
#ifdef WOLFSSL_AFALG_XILINX_AES
static const char WC_NAME_AESGCM[] = "xilinx-zynqmp-aes";
static const char* WC_TYPE_AEAD = WC_TYPE_SYMKEY;
#else
static const char WC_NAME_AESGCM[] = "gcm(aes)";
static const char WC_TYPE_AEAD[] = "aead";
#endif
#ifndef WC_SYSTEM_AESGCM_IV
/* size of IV allowed on system for AES-GCM */
#define WC_SYSTEM_AESGCM_IV 12
#endif
#ifndef WOLFSSL_MAX_AUTH_TAG_SZ
/* size of tag is restricted by system for AES-GCM
* check 'cat /proc/crypto' to see restricted size */
#define WOLFSSL_MAX_AUTH_TAG_SZ 16
#endif
#ifdef WOLFSSL_AFALG_XILINX_AES
/* Xilinx uses a slightly different function because the default AES key is also
* needed if handling additional data with creating/validating the TAG.
*
* returns 0 on success
*/
int wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len, word32 kup)
#else
int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
#endif
{
#if defined(AES_MAX_KEY_SIZE)
const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
#endif
if (aes == NULL ||
!((len == 16) || (len == 24) || (len == 32))) {
return BAD_FUNC_ARG;
}
#if defined(AES_MAX_KEY_SIZE)
/* Check key length */
if (len > max_key_len) {
return BAD_FUNC_ARG;
}
#endif
aes->keylen = len;
aes->rounds = len/4 + 6;
aes->rdFd = WC_SOCK_NOTSET;
aes->alFd = wc_Afalg_Socket();
if (aes->alFd < 0) {
WOLFSSL_MSG("Unable to open an AF_ALG socket");
return WC_AFALG_SOCK_E;
}
/* save key until direction is known i.e. encrypt or decrypt */
#ifdef WOLFSSL_AFALG_XILINX_AES
(void)kup; /* using alternate buffer because software key is needed */
XMEMCPY((byte*)(aes->msgBuf), key, len);
#else
XMEMCPY((byte*)(aes->key), key, len);
#endif
return 0;
}
/* Performs AES-GCM encryption and returns 0 on success
*
* Warning: If using Xilinx hardware acceleration it is assumed that the out
* buffer is large enough to hold both cipher text and tag. That is
* sz | 16 bytes. The input and output buffer is expected to be 64 bit
* aligned
*
*/
int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* iv, word32 ivSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
struct cmsghdr* cmsg;
struct iovec iov[3];
int ret;
struct msghdr* msg;
byte scratch[AES_BLOCK_SIZE];
/* argument checks */
if (aes == NULL || authTagSz > AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
if (ivSz != WC_SYSTEM_AESGCM_IV || authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ) {
WOLFSSL_MSG("IV/AAD size not supported on system");
return BAD_FUNC_ARG;
}
if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
aes->dir = AES_ENCRYPTION;
if ((ret = wc_AesSetup(aes, WC_TYPE_AEAD, WC_NAME_AESGCM, ivSz,
authInSz)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
/* note that if the ivSz was to change, the msg_controllen would need
reset */
#ifndef WOLFSSL_AFALG_XILINX_AES
/* set auth tag
* @TODO case where tag size changes between calls? */
ret = setsockopt(aes->alFd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL,
authTagSz);
if (ret != 0) {
perror("set tag");
WOLFSSL_MSG("Unable to set AF_ALG tag size ");
return WC_AFALG_SOCK_E;
}
#endif
}
msg = &(aes->msg);
cmsg = CMSG_FIRSTHDR(msg);
cmsg = CMSG_NXTHDR(msg, cmsg);
/* set IV and AAD size */
ret = wc_Afalg_SetIv(cmsg, (byte*)iv, ivSz);
if (ret < 0) {
WOLFSSL_MSG("Error setting IV");
return ret;
}
#ifdef WOLFSSL_AFALG_XILINX_AES
if (sz > 0) {
#ifndef NO_WOLFSSL_ALLOC_ALIGN
byte* tmp = NULL;
#endif
if ((wolfssl_word)in % WOLFSSL_XILINX_ALIGN) {
#ifndef NO_WOLFSSL_ALLOC_ALIGN
byte* tmp_align;
tmp = (byte*)XMALLOC(sz + WOLFSSL_XILINX_ALIGN +
AES_BLOCK_SIZE, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
return MEMORY_E;
}
tmp_align = tmp + (WOLFSSL_XILINX_ALIGN -
((size_t)tmp % WOLFSSL_XILINX_ALIGN));
XMEMCPY(tmp_align, in, sz);
iov[0].iov_base = tmp_align;
#else
WOLFSSL_MSG("Buffer expected to be word aligned");
return BAD_ALIGN_E;
#endif
}
else {
iov[0].iov_base = (byte*)in;
}
iov[0].iov_len = sz + AES_BLOCK_SIZE;
msg->msg_iov = iov;
msg->msg_iovlen = 1; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, msg, 0);
#ifndef NO_WOLFSSL_ALLOC_ALIGN
XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
if (ret < 0) {
return ret;
}
ret = read(aes->rdFd, out, sz + AES_BLOCK_SIZE);
if (ret < 0) {
return ret;
}
XMEMCPY(authTag, out + sz, authTagSz);
}
/* handle completing tag with using software if additional data added */
if (authIn != NULL && authInSz > 0) {
byte initalCounter[AES_BLOCK_SIZE];
XMEMSET(initalCounter, 0, AES_BLOCK_SIZE);
XMEMCPY(initalCounter, iv, ivSz);
initalCounter[AES_BLOCK_SIZE - 1] = 1;
GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
wc_AesEncryptDirect(aes, scratch, initalCounter);
xorbuf(authTag, scratch, authTagSz);
}
#else
if (authInSz > 0) {
cmsg = CMSG_NXTHDR(msg, cmsg);
ret = wc_Afalg_SetAad(cmsg, authInSz);
if (ret < 0) {
WOLFSSL_MSG("Unable to set AAD size");
return ret;
}
}
/* set data to be encrypted*/
iov[0].iov_base = (byte*)authIn;
iov[0].iov_len = authInSz;
iov[1].iov_base = (byte*)in;
iov[1].iov_len = sz;
msg->msg_iov = iov;
msg->msg_iovlen = 2; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, msg, 0);
if (ret < 0) {
return ret;
}
{
byte* tmp = (byte*)XMALLOC(authInSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
return MEMORY_E;
}
/* first 16 bytes was all 0's */
iov[0].iov_base = tmp;
(void)scratch;
iov[0].iov_len = authInSz;
iov[1].iov_base = out;
iov[1].iov_len = sz;
iov[2].iov_base = authTag;
iov[2].iov_len = authTagSz;
ret = (int)readv(aes->rdFd, iov, 3);
XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
if (ret < 0) {
return ret;
}
#endif
return 0;
}
#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT)
/* Performs AES-GCM decryption and returns 0 on success
*
* Warning: If using Xilinx hardware acceleration it is assumed that the in
* buffer is large enough to hold both cipher text and tag. That is
* sz | 16 bytes
*/
int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* iv, word32 ivSz,
const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
struct cmsghdr* cmsg;
struct msghdr* msg;
struct iovec iov[3];
byte scratch[AES_BLOCK_SIZE];
int ret;
#ifdef WOLFSSL_AFALG_XILINX_AES
byte* tag = (byte*)authTag;
byte buf[AES_BLOCK_SIZE];
byte initalCounter[AES_BLOCK_SIZE];
#ifndef NO_WOLFSSL_ALLOC_ALIGN
byte* tmp = NULL;
#endif
#endif
/* argument checks */
if (aes == NULL || authTagSz > AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
if (ivSz != WC_SYSTEM_AESGCM_IV || authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ) {
WOLFSSL_MSG("IV/AAD size not supported on system");
return BAD_FUNC_ARG;
}
if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
return BAD_FUNC_ARG;
}
if (aes->rdFd == WC_SOCK_NOTSET) {
aes->dir = AES_DECRYPTION;
if ((ret = wc_AesSetup(aes, WC_TYPE_AEAD, WC_NAME_AESGCM, ivSz,
authInSz)) != 0) {
WOLFSSL_MSG("Error with first time setup of AF_ALG socket");
return ret;
}
#ifndef WOLFSSL_AFALG_XILINX_AES
/* set auth tag
* @TODO case where tag size changes between calls? */
ret = setsockopt(aes->alFd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL,
authTagSz);
if (ret != 0) {
WOLFSSL_MSG("Unable to set AF_ALG tag size ");
return WC_AFALG_SOCK_E;
}
#endif
}
/* set IV and AAD size */
msg = &aes->msg;
if ((cmsg = CMSG_FIRSTHDR(msg)) == NULL) {
return WC_AFALG_SOCK_E;
}
if (wc_Afalg_SetOp(cmsg, aes->dir) < 0) {
WOLFSSL_MSG("Error with setting AF_ALG operation");
return WC_AFALG_SOCK_E;
}
if ((cmsg = CMSG_NXTHDR(msg, cmsg)) == NULL) {
return WC_AFALG_SOCK_E;
}
ret = wc_Afalg_SetIv(cmsg, (byte*)iv, ivSz);
if (ret < 0) {
return ret;
}
#ifdef WOLFSSL_AFALG_XILINX_AES
/* check for and handle additional data */
if (authIn != NULL && authInSz > 0) {
XMEMSET(initalCounter, 0, AES_BLOCK_SIZE);
XMEMCPY(initalCounter, iv, ivSz);
initalCounter[AES_BLOCK_SIZE - 1] = 1;
tag = buf;
GHASH(aes, NULL, 0, in, sz, tag, AES_BLOCK_SIZE);
wc_AesEncryptDirect(aes, scratch, initalCounter);
xorbuf(tag, scratch, AES_BLOCK_SIZE);
if (ret != 0) {
return AES_GCM_AUTH_E;
}
}
/* it is assumed that in buffer size is large enough to hold TAG */
XMEMCPY((byte*)in + sz, tag, AES_BLOCK_SIZE);
if ((wolfssl_word)in % WOLFSSL_XILINX_ALIGN) {
#ifndef NO_WOLFSSL_ALLOC_ALIGN
byte* tmp_align;
tmp = (byte*)XMALLOC(sz + WOLFSSL_XILINX_ALIGN +
AES_BLOCK_SIZE, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
return MEMORY_E;
}
tmp_align = tmp + (WOLFSSL_XILINX_ALIGN -
((size_t)tmp % WOLFSSL_XILINX_ALIGN));
XMEMCPY(tmp_align, in, sz + AES_BLOCK_SIZE);
iov[0].iov_base = tmp_align;
#else
WOLFSSL_MSG("Buffer expected to be word aligned");
return BAD_ALIGN_E;
#endif
}
else {
iov[0].iov_base = (byte*)in;
}
iov[0].iov_len = sz + AES_BLOCK_SIZE;
msg->msg_iov = iov;
msg->msg_iovlen = 1;
ret = sendmsg(aes->rdFd, msg, 0);
#ifndef NO_WOLFSSL_ALLOC_ALIGN
XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
if (ret < 0) {
return ret;
}
ret = read(aes->rdFd, out, sz + AES_BLOCK_SIZE);
if (ret < 0) {
return AES_GCM_AUTH_E;
}
/* check on tag */
if (authIn != NULL && authInSz > 0) {
GHASH(aes, authIn, authInSz, in, sz, tag, AES_BLOCK_SIZE);
wc_AesEncryptDirect(aes, scratch, initalCounter);
xorbuf(tag, scratch, AES_BLOCK_SIZE);
if (ConstantCompare(tag, authTag, authTagSz) != 0) {
return AES_GCM_AUTH_E;
}
}
#else
if (authInSz > 0) {
cmsg = CMSG_NXTHDR(msg, cmsg);
ret = wc_Afalg_SetAad(cmsg, authInSz);
if (ret < 0) {
return ret;
}
}
/* set data to be decrypted*/
iov[0].iov_base = (byte*)authIn;
iov[0].iov_len = authInSz;
iov[1].iov_base = (byte*)in;
iov[1].iov_len = sz;
iov[2].iov_base = (byte*)authTag;
iov[2].iov_len = authTagSz;
msg->msg_iov = iov;
msg->msg_iovlen = 3; /* # of iov structures */
ret = (int)sendmsg(aes->rdFd, &(aes->msg), 0);
if (ret < 0) {
return ret;
}
{
byte* tmp = (byte*)XMALLOC(authInSz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
return MEMORY_E;
}
iov[0].iov_base = tmp;
iov[0].iov_len = authInSz;
iov[1].iov_base = out;
iov[1].iov_len = sz;
ret = (int)readv(aes->rdFd, iov, 2);
XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
if (ret < 0) {
return AES_GCM_AUTH_E;
}
(void)scratch;
#endif
return 0;
}
#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */
#endif /* HAVE_AESGCM */
#ifdef HAVE_AES_ECB
int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_Afalg_AesDirect(aes, out, in, sz);
}
int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_Afalg_AesDirect(aes, out, in, sz);
}
#endif /* HAVE_AES_ECB */
#endif /* !NO_AES && WOLFSSL_AFALG */

View file

@ -1,339 +0,0 @@
/* afalg_hash.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_AFALG_HASH) || (defined(WOLFSSL_AFALG_XILINX_SHA3) \
&& defined(WOLFSSL_SHA3))
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
#include <wolfssl/wolfcrypt/port/af_alg/afalg_hash.h>
static const char WC_TYPE_HASH[] = "hash";
/* generic AF_ALG hash free */
static void AfalgHashFree(wolfssl_AFALG_Hash* hash)
{
if (hash == NULL)
return;
if (hash->alFd > 0) {
close(hash->alFd);
hash->alFd = -1; /* avoid possible double close on socket */
}
if (hash->rdFd > 0) {
close(hash->rdFd);
hash->rdFd = -1; /* avoid possible double close on socket */
}
#if defined(WOLFSSL_AFALG_HASH_KEEP)
if (hash->msg != NULL) {
XFREE(hash->msg, hash->heap, DYNAMIC_TYPE_TMP_BUFFER);
hash->msg = NULL;
}
#endif
}
/* generic hash init for AF_ALG, returns 0 on success */
static int AfalgHashInit(wolfssl_AFALG_Hash* hash, void* heap, int devId,
const char* type)
{
if (hash == NULL) {
return BAD_FUNC_ARG;
}
(void)devId; /* no async for now */
XMEMSET(hash, 0, sizeof(wolfssl_AFALG_Hash));
hash->heap = heap;
hash->len = 0;
hash->used = 0;
hash->msg = NULL;
hash->alFd = -1;
hash->rdFd = -1;
hash->alFd = wc_Afalg_Socket();
if (hash->alFd < 0) {
return WC_AFALG_SOCK_E;
}
hash->rdFd = wc_Afalg_CreateRead(hash->alFd, WC_TYPE_HASH, type);
if (hash->rdFd < 0) {
close(hash->alFd);
return WC_AFALG_SOCK_E;
}
return 0;
}
/* generic hash update for AF_ALG, returns 0 on success */
static int AfalgHashUpdate(wolfssl_AFALG_Hash* hash, const byte* in, word32 sz)
{
if (hash == NULL || (sz > 0 && in == NULL)) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_AFALG_HASH_KEEP
/* keep full message to hash at end instead of incremental updates */
if (hash->len < hash->used + sz) {
if (hash->msg == NULL) {
hash->msg = (byte*)XMALLOC(hash->used + sz, hash->heap,
DYNAMIC_TYPE_TMP_BUFFER);
} else {
byte* pt = (byte*)XREALLOC(hash->msg, hash->used + sz, hash->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pt == NULL) {
return MEMORY_E;
}
hash->msg = pt;
}
if (hash->msg == NULL) {
return MEMORY_E;
}
hash->len = hash->used + sz;
}
XMEMCPY(hash->msg + hash->used, in, sz);
hash->used += sz;
#else
int ret;
if ((ret = (int)send(hash->rdFd, in, sz, MSG_MORE)) < 0) {
return ret;
}
#endif
return 0;
}
/* generic hash final for AF_ALG, return 0 on success */
static int AfalgHashFinal(wolfssl_AFALG_Hash* hash, byte* out, word32 outSz,
const char* type)
{
int ret;
void* heap;
if (hash == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
heap = hash->heap; /* keep because AfalgHashInit clears the pointer */
#ifdef WOLFSSL_AFALG_HASH_KEEP
/* keep full message to out at end instead of incremental updates */
if ((ret = (int)send(hash->rdFd, hash->msg, hash->used, 0)) < 0) {
return ret;
}
XFREE(hash->msg, heap, DYNAMIC_TYPE_TMP_BUFFER);
hash->msg = NULL;
#else
if ((ret = (int)send(hash->rdFd, NULL, 0, 0)) < 0) {
return ret;
}
#endif
if ((ret = (int)read(hash->rdFd, out, outSz)) != (int)outSz) {
return ret;
}
AfalgHashFree(hash);
return AfalgHashInit(hash, heap, 0, type);
}
/* generic function to get intermediate hash */
static int AfalgHashGet(wolfssl_AFALG_Hash* hash, byte* out, word32 outSz)
{
int ret;
if (hash == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
(void)ret;
#ifdef WOLFSSL_AFALG_HASH_KEEP
if ((ret = (int)send(hash->rdFd, hash->msg, hash->used, 0)) < 0) {
return ret;
}
if ((ret = (int)read(hash->rdFd, out, outSz)) != (int)outSz) {
return ret;
}
return 0;
#else
(void)hash;
(void)out;
(void)outSz;
WOLFSSL_MSG("Compile with WOLFSSL_AFALG_HASH_KEEP for this feature");
return NOT_COMPILED_IN;
#endif
}
/* generic struct copy for AF_ALG, returns 0 on success */
static int AfalgHashCopy(wolfssl_AFALG_Hash* src, wolfssl_AFALG_Hash* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
XMEMCPY(dst, src, sizeof(wolfssl_AFALG_Hash));
#ifdef WOLFSSL_AFALG_HASH_KEEP
dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (dst->msg == NULL) {
return MEMORY_E;
}
XMEMCPY(dst->msg, src->msg, src->len);
#endif
dst->rdFd = accept(src->rdFd, NULL, 0);
dst->alFd = accept(src->alFd, NULL, 0);
if (dst->rdFd == -1 || dst->alFd == -1) {
AfalgHashFree(dst);
return -1;
}
return 0;
}
#if !defined(NO_SHA256) && defined(WOLFSSL_AFALG_HASH)
#include <wolfssl/wolfcrypt/sha256.h>
static const char WC_NAME_SHA256[] = "sha256";
/* create AF_ALG sockets for SHA256 operation */
int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
{
return AfalgHashInit(sha, heap, devId, WC_NAME_SHA256);
}
int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz)
{
return AfalgHashUpdate(sha, in, sz);
}
int wc_Sha256Final(wc_Sha256* sha, byte* hash)
{
return AfalgHashFinal(sha, hash, WC_SHA256_DIGEST_SIZE, WC_NAME_SHA256);
}
int wc_Sha256GetHash(wc_Sha256* sha, byte* hash)
{
return AfalgHashGet(sha, hash, WC_SHA256_DIGEST_SIZE);
}
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
{
return AfalgHashCopy(src, dst);
}
#endif /* !NO_SHA256 */
#if defined(WOLFSSL_SHA3) && defined(WOLFSSL_AFALG_XILINX_SHA3)
#include <wolfssl/wolfcrypt/sha3.h>
static const char WC_NAME_SHA3[] = "xilinx-keccak-384";
void wc_Sha3_384_Free(wc_Sha3* sha)
{
AfalgHashFree(sha);
}
/* create AF_ALG sockets for SHA256 operation */
int wc_InitSha3_384(wc_Sha3* sha, void* heap, int devId)
{
return AfalgHashInit(sha, heap, devId, WC_NAME_SHA3);
}
int wc_Sha3_384_Update(wc_Sha3* sha, const byte* in, word32 sz)
{
#ifndef WOLFSSL_AFALG_HASH_KEEP
if (sz % 4) {
WOLFSSL_MSG("Alignment issue. Message size needs to be divisible by 4")
return BAD_FUNC_ARG;
}
#endif
return AfalgHashUpdate(sha, in, sz);
}
int wc_Sha3_384_Final(wc_Sha3* sha, byte* hash)
{
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_AFALG_HASH_KEEP
if (sha->used % 4) {
WOLFSSL_MSG("Alignment issue. Message size needs to be divisible by 4");
return BAD_FUNC_ARG;
}
#endif
return AfalgHashFinal(sha, hash, WC_SHA3_384_DIGEST_SIZE, WC_NAME_SHA3);
}
int wc_Sha3_384_GetHash(wc_Sha3* sha, byte* hash)
{
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_AFALG_HASH_KEEP
if (sha->used % 4) {
WOLFSSL_MSG("Alignment issue. Message size needs to be divisible by 4");
return BAD_FUNC_ARG;
}
#endif
return AfalgHashGet(sha, hash, WC_SHA3_384_DIGEST_SIZE);
}
int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst)
{
return AfalgHashCopy(src, dst);
}
#endif /* WOLFSSL_SHA3 && WOLFSSL_AFALG_XILINX_SHA3 */
#endif /* WOLFSSL_AFALG */

View file

@ -1,141 +0,0 @@
/* wc_afalg.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX)
#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
#include <linux/if_alg.h>
/* Sets the type of socket address to use */
void wc_Afalg_SockAddr(struct sockaddr_alg* in, const char* type, const char* name)
{
in->salg_family = AF_ALG;
XSTRNCPY((char*)in->salg_type, type, XSTRLEN(type));
in->salg_type[XSTRLEN(type)] = '\0';
XSTRNCPY((char*)in->salg_name, name, XSTRLEN(name));
in->salg_name[XSTRLEN(name)] = '\0';
}
/* returns the socket accepting on with success
* negative values are returned in fail cases */
int wc_Afalg_Accept(struct sockaddr_alg* in, int inSz, int sock)
{
if (bind(sock, (const struct sockaddr*)in, inSz) < 0) {
WOLFSSL_MSG("Failed to bind with AF_ALG");
return WC_AFALG_SOCK_E;
}
return accept(sock, NULL, 0);
}
/* creates a new AF_ALG socket and returns it
* negative values are returned in fail cases */
int wc_Afalg_Socket(void)
{
int sock;
if ((sock = socket(AF_ALG, SOCK_SEQPACKET, 0)) < 0) {
WOLFSSL_MSG("Failed to get AF_ALG socket");
return WC_AFALG_SOCK_E;
}
return sock;
}
/* binds and creates the read fd */
int wc_Afalg_CreateRead(int sock, const char* type, const char* name)
{
struct sockaddr_alg sa = {0};
wc_Afalg_SockAddr(&sa, type, name);
return wc_Afalg_Accept(&sa, sizeof(sa), sock);
}
/* sets the IV in CMSG structure, returns 0 on success */
int wc_Afalg_SetIv(struct cmsghdr* cmsg, byte* iv, word32 ivSz)
{
struct af_alg_iv* afIv;
if (cmsg == NULL || iv == NULL) {
WOLFSSL_MSG("Null cmsg or iv passed in");
return BAD_FUNC_ARG;
}
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_IV;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct af_alg_iv) + ivSz);
afIv = (void*)CMSG_DATA(cmsg);
afIv->ivlen = ivSz;
XMEMCPY(afIv->iv, iv, ivSz);
return 0;
}
/* sets the AAD size in CMSG structure, returns 0 on success */
int wc_Afalg_SetAad(struct cmsghdr* cmsg, word32 sz)
{
if (cmsg == NULL) {
WOLFSSL_MSG("Null cmsg passed in");
return BAD_FUNC_ARG;
}
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
cmsg->cmsg_len = CMSG_LEN(sizeof(word32));
*((word32*)CMSG_DATA(cmsg)) = sz;
return 0;
}
/* sets the operation type in CMSG structure, returns 0 on success
*
* dir 0 is encryption 1 is decryption
*/
int wc_Afalg_SetOp(struct cmsghdr* cmsg, int dir)
{
if (cmsg == NULL) {
return BAD_FUNC_ARG;
}
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_OP;
cmsg->cmsg_len = CMSG_LEN(4);
*((word32*)CMSG_DATA(cmsg)) = (dir == 1)? ALG_OP_DECRYPT : ALG_OP_ENCRYPT;
return 0;
}
#endif /* !NO_AES && WOLFSSL_AFALG */

File diff suppressed because it is too large Load diff

View file

@ -1,715 +0,0 @@
/* sha512.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef WOLFSSL_ARMASM
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
#include <wolfssl/wolfcrypt/sha512.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/cpuid.h>
#include <wolfssl/wolfcrypt/hash.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifdef WOLFSSL_SHA512
static int InitSha512(wc_Sha512* sha512)
{
if (sha512 == NULL)
return BAD_FUNC_ARG;
sha512->digest[0] = W64LIT(0x6a09e667f3bcc908);
sha512->digest[1] = W64LIT(0xbb67ae8584caa73b);
sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b);
sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1);
sha512->digest[4] = W64LIT(0x510e527fade682d1);
sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f);
sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b);
sha512->digest[7] = W64LIT(0x5be0cd19137e2179);
sha512->buffLen = 0;
sha512->loLen = 0;
sha512->hiLen = 0;
#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
sha512->flags = 0;
#endif
return 0;
}
#endif /* WOLFSSL_SHA512 */
#ifdef WOLFSSL_SHA512
int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId)
{
int ret = 0;
if (sha512 == NULL)
return BAD_FUNC_ARG;
sha512->heap = heap;
ret = InitSha512(sha512);
if (ret != 0)
return ret;
#ifdef WOLFSSL_SMALL_STACK_CACHE
sha512->W = NULL;
#endif
(void)devId;
return ret;
}
#endif /* WOLFSSL_SHA512 */
#ifndef WOLFSSL_ARMASM
static const word64 K512[80] = {
W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
};
#ifdef LITTLE_ENDIAN_ORDER
#define blk0(i) (W[i] = ByteReverseWord64(DATA[i]))
#else
#define blk0(i) (W[i] = DATA[i])
#endif
#define blk2(i) ( \
W[ i ] += \
s1(W[(i- 2) & 15])+ \
W[(i- 7) & 15] + \
s0(W[(i-15) & 15]) \
)
#define Ch(x,y,z) (z ^ ((z ^ y) & x))
#define Maj(x,y,z) (y ^ ((y ^ z) & (x ^ y)))
#define a(i) T[(0-i) & 7]
#define b(i) T[(1-i) & 7]
#define c(i) T[(2-i) & 7]
#define d(i) T[(3-i) & 7]
#define e(i) T[(4-i) & 7]
#define f(i) T[(5-i) & 7]
#define g(i) T[(6-i) & 7]
#define h(i) T[(7-i) & 7]
#define S0(x) (rotrFixed64(x,28) ^ rotrFixed64(x,34) ^ rotrFixed64(x,39))
#define S1(x) (rotrFixed64(x,14) ^ rotrFixed64(x,18) ^ rotrFixed64(x,41))
#define s0(x) (rotrFixed64(x, 1) ^ rotrFixed64(x, 8) ^ (x>>7))
#define s1(x) (rotrFixed64(x,19) ^ rotrFixed64(x,61) ^ (x>>6))
#define R0(i) \
h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + blk0(i); \
d(i) += h(i); \
h(i) += S0(a(i)) + Maj(a(i),b(i),c(i))
#define R(i) \
h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + blk2(i); \
d(i) += h(i); \
h(i) += S0(a(i)) + Maj(a(i),b(i),c(i))
#define DATA sha512->buffer
static void Transform_Sha512(wc_Sha512* sha512)
{
const word64* K = K512;
word32 j;
word64 T[8];
word64 W[16];
/* Copy digest to working vars */
T[0] = sha512->digest[0];
T[1] = sha512->digest[1];
T[2] = sha512->digest[2];
T[3] = sha512->digest[3];
T[4] = sha512->digest[4];
T[5] = sha512->digest[5];
T[6] = sha512->digest[6];
T[7] = sha512->digest[7];
/* 80 operations, partially loop unrolled */
j = 0;
R0( 0); R0( 1); R0( 2); R0( 3);
R0( 4); R0( 5); R0( 6); R0( 7);
R0( 8); R0( 9); R0(10); R0(11);
R0(12); R0(13); R0(14); R0(15);
for (j = 16; j < 80; j += 16) {
R( 0); R( 1); R( 2); R( 3);
R( 4); R( 5); R( 6); R( 7);
R( 8); R( 9); R(10); R(11);
R(12); R(13); R(14); R(15);
}
/* Add the working vars back into digest */
sha512->digest[0] += T[0];
sha512->digest[1] += T[1];
sha512->digest[2] += T[2];
sha512->digest[3] += T[3];
sha512->digest[4] += T[4];
sha512->digest[5] += T[5];
sha512->digest[6] += T[6];
sha512->digest[7] += T[7];
return 0;
}
#undef DATA
#define DATA ((word64*)data)
static void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, word32 len)
{
const word64* K = K512;
word32 j;
word64 T[8];
word64 TO[8];
word64 W[16];
/* Copy digest to working vars */
T[0] = sha512->digest[0];
T[1] = sha512->digest[1];
T[2] = sha512->digest[2];
T[3] = sha512->digest[3];
T[4] = sha512->digest[4];
T[5] = sha512->digest[5];
T[6] = sha512->digest[6];
T[7] = sha512->digest[7];
do {
TO[0] = T[0];
TO[1] = T[1];
TO[2] = T[2];
TO[3] = T[3];
TO[4] = T[4];
TO[5] = T[5];
TO[6] = T[6];
TO[7] = T[7];
/* 80 operations, partially loop unrolled */
j = 0;
R0( 0); R0( 1); R0( 2); R0( 3);
R0( 4); R0( 5); R0( 6); R0( 7);
R0( 8); R0( 9); R0(10); R0(11);
R0(12); R0(13); R0(14); R0(15);
for (j = 16; j < 80; j += 16) {
R( 0); R( 1); R( 2); R( 3);
R( 4); R( 5); R( 6); R( 7);
R( 8); R( 9); R(10); R(11);
R(12); R(13); R(14); R(15);
}
T[0] += TO[0];
T[1] += TO[1];
T[2] += TO[2];
T[3] += TO[3];
T[4] += TO[4];
T[5] += TO[5];
T[6] += TO[6];
T[7] += TO[7];
data += 128;
len -= 128;
}
while (len > 0);
/* Add the working vars back into digest */
sha512->digest[0] = T[0];
sha512->digest[1] = T[1];
sha512->digest[2] = T[2];
sha512->digest[3] = T[3];
sha512->digest[4] = T[4];
sha512->digest[5] = T[5];
sha512->digest[6] = T[6];
sha512->digest[7] = T[7];
return 0;
}
#undef DATA
#endif
static WC_INLINE void AddLength(wc_Sha512* sha512, word32 len)
{
word64 tmp = sha512->loLen;
if ( (sha512->loLen += len) < tmp)
sha512->hiLen++; /* carry low to high */
}
static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
{
int ret = 0;
/* do block size increments */
byte* local = (byte*)sha512->buffer;
word32 blocksLen;
/* check that internal buffLen is valid */
if (sha512->buffLen >= WC_SHA512_BLOCK_SIZE)
return BUFFER_E;
AddLength(sha512, len);
if (sha512->buffLen > 0) {
word32 add = min(len, WC_SHA512_BLOCK_SIZE - sha512->buffLen);
if (add > 0) {
XMEMCPY(&local[sha512->buffLen], data, add);
sha512->buffLen += add;
data += add;
len -= add;
}
if (sha512->buffLen == WC_SHA512_BLOCK_SIZE) {
#ifndef WOLFSSL_ARMASM
Transform_Sha512(sha512);
#else
Transform_Sha512_Len(sha512, (const byte*)sha512->buffer,
WC_SHA512_BLOCK_SIZE);
#endif
sha512->buffLen = 0;
}
}
blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1);
if (blocksLen > 0) {
/* Byte reversal performed in function if required. */
Transform_Sha512_Len(sha512, data, blocksLen);
data += blocksLen;
len -= blocksLen;
}
if (len > 0) {
XMEMCPY(local, data, len);
sha512->buffLen = len;
}
return ret;
}
#ifdef WOLFSSL_SHA512
int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
{
if (sha512 == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
return Sha512Update(sha512, data, len);
}
#endif /* WOLFSSL_SHA512 */
static WC_INLINE int Sha512Final(wc_Sha512* sha512)
{
byte* local = (byte*)sha512->buffer;
if (sha512 == NULL) {
return BAD_FUNC_ARG;
}
local[sha512->buffLen++] = 0x80; /* add 1 */
/* pad with zeros */
if (sha512->buffLen > WC_SHA512_PAD_SIZE) {
XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_BLOCK_SIZE -
sha512->buffLen);
sha512->buffLen += WC_SHA512_BLOCK_SIZE - sha512->buffLen;
#ifndef WOLFSSL_ARMASM
Transform_Sha512(sha512);
#else
Transform_Sha512_Len(sha512, (const byte*)sha512->buffer,
WC_SHA512_BLOCK_SIZE);
#endif
sha512->buffLen = 0;
}
XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_PAD_SIZE - sha512->buffLen);
/* put lengths in bits */
sha512->hiLen = (sha512->loLen >> (8 * sizeof(sha512->loLen) - 3)) +
(sha512->hiLen << 3);
sha512->loLen = sha512->loLen << 3;
/* store lengths */
/* ! length ordering dependent on digest endian type ! */
sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
ByteReverseWords64(
&(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]),
&(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]),
WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE);
#ifndef WOLFSSL_ARMASM
Transform_Sha512(sha512);
#else
Transform_Sha512_Len(sha512, (const byte*)sha512->buffer,
WC_SHA512_BLOCK_SIZE);
#endif
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64(sha512->digest, sha512->digest, WC_SHA512_DIGEST_SIZE);
#endif
return 0;
}
#ifdef WOLFSSL_SHA512
int wc_Sha512FinalRaw(wc_Sha512* sha512, byte* hash)
{
#ifdef LITTLE_ENDIAN_ORDER
word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)];
#endif
if (sha512 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64((word64*)digest, (word64*)sha512->digest,
WC_SHA512_DIGEST_SIZE);
XMEMCPY(hash, digest, WC_SHA512_DIGEST_SIZE);
#else
XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE);
#endif
return 0;
}
int wc_Sha512Final(wc_Sha512* sha512, byte* hash)
{
int ret;
if (sha512 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = Sha512Final(sha512);
if (ret != 0)
return ret;
XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE);
return InitSha512(sha512); /* reset state */
}
int wc_InitSha512(wc_Sha512* sha512)
{
return wc_InitSha512_ex(sha512, NULL, INVALID_DEVID);
}
void wc_Sha512Free(wc_Sha512* sha512)
{
if (sha512 == NULL)
return;
#ifdef WOLFSSL_SMALL_STACK_CACHE
if (sha512->W != NULL) {
XFREE(sha512->W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sha512->W = NULL;
}
#endif
}
#endif /* WOLFSSL_SHA512 */
/* -------------------------------------------------------------------------- */
/* SHA384 */
/* -------------------------------------------------------------------------- */
#ifdef WOLFSSL_SHA384
static int InitSha384(wc_Sha384* sha384)
{
if (sha384 == NULL) {
return BAD_FUNC_ARG;
}
sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
sha384->digest[1] = W64LIT(0x629a292a367cd507);
sha384->digest[2] = W64LIT(0x9159015a3070dd17);
sha384->digest[3] = W64LIT(0x152fecd8f70e5939);
sha384->digest[4] = W64LIT(0x67332667ffc00b31);
sha384->digest[5] = W64LIT(0x8eb44a8768581511);
sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7);
sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4);
sha384->buffLen = 0;
sha384->loLen = 0;
sha384->hiLen = 0;
#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
sha384->flags = 0;
#endif
return 0;
}
int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len)
{
if (sha384 == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
return Sha512Update((wc_Sha512*)sha384, data, len);
}
int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash)
{
#ifdef LITTLE_ENDIAN_ORDER
word64 digest[WC_SHA384_DIGEST_SIZE / sizeof(word64)];
#endif
if (sha384 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
#ifdef LITTLE_ENDIAN_ORDER
ByteReverseWords64((word64*)digest, (word64*)sha384->digest,
WC_SHA384_DIGEST_SIZE);
XMEMCPY(hash, digest, WC_SHA384_DIGEST_SIZE);
#else
XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
#endif
return 0;
}
int wc_Sha384Final(wc_Sha384* sha384, byte* hash)
{
int ret;
if (sha384 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = Sha512Final((wc_Sha512*)sha384);
if (ret != 0)
return ret;
XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE);
return InitSha384(sha384); /* reset state */
}
int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId)
{
int ret;
if (sha384 == NULL) {
return BAD_FUNC_ARG;
}
sha384->heap = heap;
ret = InitSha384(sha384);
if (ret != 0)
return ret;
#ifdef WOLFSSL_SMALL_STACK_CACHE
sha384->W = NULL;
#endif
(void)devId;
return ret;
}
int wc_InitSha384(wc_Sha384* sha384)
{
return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID);
}
void wc_Sha384Free(wc_Sha384* sha384)
{
if (sha384 == NULL)
return;
#ifdef WOLFSSL_SMALL_STACK_CACHE
if (sha384->W != NULL) {
XFREE(sha384->W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sha384->W = NULL;
}
#endif
}
#endif /* WOLFSSL_SHA384 */
#ifdef WOLFSSL_SHA512
int wc_Sha512GetHash(wc_Sha512* sha512, byte* hash)
{
int ret;
wc_Sha512 tmpSha512;
if (sha512 == NULL || hash == NULL)
return BAD_FUNC_ARG;
ret = wc_Sha512Copy(sha512, &tmpSha512);
if (ret == 0) {
ret = wc_Sha512Final(&tmpSha512, hash);
wc_Sha512Free(&tmpSha512);
}
return ret;
}
int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst)
{
int ret = 0;
if (src == NULL || dst == NULL)
return BAD_FUNC_ARG;
XMEMCPY(dst, src, sizeof(wc_Sha512));
#ifdef WOLFSSL_SMALL_STACK_CACHE
dst->W = NULL;
#endif
#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
dst->flags |= WC_HASH_FLAG_ISCOPY;
#endif
return ret;
}
#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags)
{
if (sha512) {
sha512->flags = flags;
}
return 0;
}
int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags)
{
if (sha512 && flags) {
*flags = sha512->flags;
}
return 0;
}
#endif
#endif /* WOLFSSL_SHA512 */
#ifdef WOLFSSL_SHA384
int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash)
{
int ret;
wc_Sha384 tmpSha384;
if (sha384 == NULL || hash == NULL)
return BAD_FUNC_ARG;
ret = wc_Sha384Copy(sha384, &tmpSha384);
if (ret == 0) {
ret = wc_Sha384Final(&tmpSha384, hash);
wc_Sha384Free(&tmpSha384);
}
return ret;
}
int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst)
{
int ret = 0;
if (src == NULL || dst == NULL)
return BAD_FUNC_ARG;
XMEMCPY(dst, src, sizeof(wc_Sha384));
#ifdef WOLFSSL_SMALL_STACK_CACHE
dst->W = NULL;
#endif
#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
dst->flags |= WC_HASH_FLAG_ISCOPY;
#endif
return ret;
}
#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB)
int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags)
{
if (sha384) {
sha384->flags = flags;
}
return 0;
}
int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags)
{
if (sha384 && flags) {
*flags = sha384->flags;
}
return 0;
}
#endif
#endif /* WOLFSSL_SHA384 */
#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */
#endif /* WOLFSSL_ARMASM */

View file

@ -1,309 +0,0 @@
/* cryptoCell.c
*
* Copyright (C) 2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
/* This source is included in wc_port.c */
/* WOLFSSL_CRYPTOCELL_C is defined by wc_port.c in case compile tries to
include this .c directly */
#ifdef WOLFSSL_CRYPTOCELL_C
#ifdef WOLFSSL_CRYPTOCELL
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/port/arm/cryptoCell.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
/* Global Variables (extern) */
CRYS_RND_State_t wc_rndState;
CRYS_RND_WorkBuff_t wc_rndWorkBuff;
SaSiRndGenerateVectWorkFunc_t wc_rndGenVectFunc = CRYS_RND_GenerateVector;
static word32 cc310_enableCount = 0;
static void cc310_enable(void)
{
cc310_enableCount++;
/* Enable the CC310 HW/IQ once*/
NRF_CRYPTOCELL->ENABLE = 1;
NVIC_EnableIRQ(CRYPTOCELL_IRQn);
}
static void cc310_disable(void)
{
cc310_enableCount--;
/* Disable HW/IRQ if no more users */
if (cc310_enableCount == 0) {
NRF_CRYPTOCELL->ENABLE = 0;
NVIC_DisableIRQ(CRYPTOCELL_IRQn);
}
}
int cc310_Init(void)
{
int ret = 0;
static int initialized = 0;
if (!initialized) {
/* Enable the CC310 HW. */
cc310_enable();
/*Initialize the CC310 run-time library*/
ret = SaSi_LibInit();
if (ret != SA_SILIB_RET_OK) {
WOLFSSL_MSG("Error SaSi_LibInit");
return ret;
}
/* RNG CryptoCell CC310 */
ret = CRYS_RndInit(&wc_rndState, &wc_rndWorkBuff);
if (ret != CRYS_OK) {
WOLFSSL_MSG("Error CRYS_RndInit");
return ret;
}
initialized = 1;
}
return ret;
}
void cc310_Free(void)
{
CRYSError_t crys_result;
SaSi_LibFini();
crys_result = CRYS_RND_UnInstantiation(&wc_rndState);
if (crys_result != CRYS_OK) {
WOLFSSL_MSG("Error RYS_RND_UnInstantiation");
}
cc310_disable();
}
int cc310_random_generate(byte* output, word32 size)
{
CRYSError_t crys_result;
crys_result = CRYS_RND_GenerateVector(&wc_rndState, size, output);
return (crys_result == CRYS_OK) ? 0 : -1;
}
#ifdef HAVE_ECC
CRYS_ECPKI_DomainID_t cc310_mapCurve(int curve_id)
{
switch(curve_id)
{
case ECC_CURVE_DEF: return CRYS_ECPKI_DomainID_secp256r1; /* default */
case ECC_SECP160K1: return CRYS_ECPKI_DomainID_secp160k1;
case ECC_SECP160R1: return CRYS_ECPKI_DomainID_secp160r1;
case ECC_SECP160R2: return CRYS_ECPKI_DomainID_secp160r2;
case ECC_SECP192K1: return CRYS_ECPKI_DomainID_secp192k1;
case ECC_SECP192R1: return CRYS_ECPKI_DomainID_secp192r1;
case ECC_SECP224K1: return CRYS_ECPKI_DomainID_secp224k1;
case ECC_SECP224R1: return CRYS_ECPKI_DomainID_secp224r1;
case ECC_SECP256K1: return CRYS_ECPKI_DomainID_secp256k1;
case ECC_SECP256R1: return CRYS_ECPKI_DomainID_secp256r1;
case ECC_SECP384R1: return CRYS_ECPKI_DomainID_secp384r1;
case ECC_SECP521R1: return CRYS_ECPKI_DomainID_secp521r1;
default: WOLFSSL_MSG("Curve not identified");
return CRYS_ECPKI_DomainID_Builded;
}
}
#endif /* HAVE_ECC */
#ifndef NO_RSA
CRYS_RSA_HASH_OpMode_t cc310_hashModeRSA(enum wc_HashType hash_type, int isHashed)
{
switch(hash_type)
{
case WC_HASH_TYPE_MD5:
#ifndef NO_MD5
return isHashed? CRYS_RSA_After_MD5_mode : CRYS_RSA_HASH_MD5_mode;
#endif
case WC_HASH_TYPE_SHA:
#ifndef NO_SHA
return isHashed? CRYS_RSA_After_SHA1_mode : CRYS_RSA_HASH_SHA1_mode;
#endif
case WC_HASH_TYPE_SHA224:
#ifdef WOLFSSL_SHA224
return isHashed? CRYS_RSA_After_SHA224_mode : CRYS_RSA_HASH_SHA224_mode;
#endif
case WC_HASH_TYPE_SHA256:
#ifndef NO_SHA256
return isHashed? CRYS_RSA_After_SHA256_mode : CRYS_RSA_HASH_SHA256_mode;
#endif
case WC_HASH_TYPE_SHA384:
#ifdef WOLFSSL_SHA384
return isHashed? CRYS_RSA_After_SHA384_mode : CRYS_RSA_HASH_SHA384_mode;
#endif
case WC_HASH_TYPE_SHA512:
#ifdef WOLFSSL_SHA512
return isHashed? CRYS_RSA_After_SHA512_mode : CRYS_RSA_HASH_SHA512_mode;
#endif
case WC_HASH_TYPE_NONE:
/* default to SHA256 */
return isHashed? CRYS_RSA_After_SHA256_mode : CRYS_RSA_HASH_SHA256_mode;
default:
return CRYS_RSA_After_HASH_NOT_KNOWN_mode;
}
}
#endif /* !NO_RSA */
#ifdef HAVE_ECC
CRYS_ECPKI_HASH_OpMode_t cc310_hashModeECC(int hash_size)
{
CRYS_ECPKI_HASH_OpMode_t hash_mode;
switch (hash_size)
{
case 20:
hash_mode = CRYS_ECPKI_AFTER_HASH_SHA1_mode;
break;
case 28:
hash_mode = CRYS_ECPKI_AFTER_HASH_SHA224_mode;
break;
case 32:
hash_mode = CRYS_ECPKI_AFTER_HASH_SHA256_mode;
break;
case 48:
hash_mode = CRYS_ECPKI_AFTER_HASH_SHA384_mode;
break;
case 64:
hash_mode = CRYS_ECPKI_AFTER_HASH_SHA512_mode;
break;
default:
hash_mode = CRYS_ECPKI_HASH_OpModeLast;
break;
}
return hash_mode;
}
#endif /* HAVE_ECC */
#endif /* WOLFSSL_CRYPTOCELL*/
#if !defined(NO_CRYPT_BENCHMARK) && defined(WOLFSSL_nRF5x_SDK_15_2)
static int mRtcSec = 0;
static const nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(0);
static void rtc_handler(nrfx_rtc_int_type_t int_type)
{
if (int_type == NRFX_RTC_INT_COMPARE0) {
mRtcSec++;
nrfx_rtc_counter_clear(&rtc);
nrfx_rtc_int_enable(&rtc, RTC_CHANNEL_INT_MASK(0));
#ifdef BSP_LED_1
nrf_gpio_pin_toggle(BSP_LED_1);
#endif
}
else if (int_type == NRF_DRV_RTC_INT_TICK) {
#ifdef BSP_LED_0
nrf_gpio_pin_toggle(BSP_LED_0);
#endif
}
}
static void rtc_config(void)
{
uint32_t err_code;
nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
/* configure gpio for pin toggling. */
bsp_board_init(BSP_INIT_LEDS);
/* start the internal LFCLK XTAL oscillator.*/
err_code = nrf_drv_clock_init();
APP_ERROR_CHECK(err_code);
nrf_drv_clock_lfclk_request(NULL);
/* Initialize RTC instance */
err_code = nrfx_rtc_init(&rtc, &config, rtc_handler);
APP_ERROR_CHECK(err_code);
/* Enable tick event */
nrfx_rtc_tick_enable(&rtc, false);
/* Set compare channel to trigger interrupt after 1 seconds */
err_code = nrfx_rtc_cc_set(&rtc, 0, RTC_INPUT_FREQ, true);
APP_ERROR_CHECK(err_code);
/* Power on RTC instance */
nrfx_rtc_enable(&rtc);
}
static int rtc_get_ms(void)
{
/* Prescaler is 12-bit for COUNTER: frequency = (32768/(PRESCALER+1)) */
int frequency = (RTC_INPUT_FREQ / (rtc_prescaler_get(rtc.p_reg) + 1));
uint32_t counter = nrfx_rtc_counter_get(&rtc);
/* Convert with rounding frequency to milliseconds */
return ((counter * 1000) + (frequency / 2) ) / frequency;
}
double current_time(int reset)
{
double time;
static int initialized = 0;
if (!initialized) {
rtc_config();
initialized = 1;
}
time = mRtcSec;
time += (double)rtc_get_ms() / 1000;
return time;
}
int nrf_random_generate(byte* output, word32 size)
{
uint32_t err_code;
static int initialized = 0;
/* RNG must be initialized once */
if (!initialized) {
err_code = nrf_drv_rng_init(NULL);
if (err_code != NRF_SUCCESS) {
return -1;
}
initialized = 1;
}
nrf_drv_rng_block_rand(output, size);
return 0;
}
#endif /* !NO_CRYPT_BENCHMARK && WOLFSSL_nRF5x_SDK_15_2 */
#endif /* WOLFSSL_CRYPTOCELL_C */

View file

@ -1,134 +0,0 @@
/* cryptoCellHash.c
*
* Copyright (C) 2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
/* This source is included in wc_port.c */
/* WOLFSSL_CRYPTOCELL_HASH_C is defined by wc_port.c in case compile tries
to include this .c directly */
#ifdef WOLFSSL_CRYPTOCELL_HASH_C
#if !defined(NO_SHA256) && defined(WOLFSSL_CRYPTOCELL)
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/port/arm/cryptoCell.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
{
CRYSError_t ret = 0;
(void)heap;
(void)devId;
if (sha256 == NULL)
return BAD_FUNC_ARG;
XMEMSET(sha256->digest, 0, sizeof(sha256->digest));
/* initializes the HASH context and machine to the supported mode.*/
ret = CRYS_HASH_Init(&sha256->ctx, CRYS_HASH_SHA256_mode);
if (ret != SA_SILIB_RET_OK){
WOLFSSL_MSG("Error CRYS_HASH_Init failed");
}
return ret;
}
int wc_InitSha256(Sha256* sha256)
{
return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
}
int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
{
CRYSError_t ret = 0;
size_t length;
size_t remaining = len;
byte const * p_cur = data;
if (sha256 == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
if (data == NULL && len == 0) {
/* valid, but do nothing */
return 0;
}
/* If the input is larger than CC310_MAX_LENGTH_DMA, split into smaller */
do {
length = (remaining > CC310_MAX_LENGTH_DMA) ?
CC310_MAX_LENGTH_DMA : remaining;
ret = CRYS_HASH_Update(&sha256->ctx, (uint8_t *)p_cur, length);
remaining -= length;
p_cur += length;
} while (ret == CRYS_OK && remaining > 0);
return ret;
}
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
{
CRYSError_t ret = 0;
CRYS_HASH_Result_t hashResult;
if (sha256 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = CRYS_HASH_Finish(&sha256->ctx, hashResult);
if (ret != SA_SILIB_RET_OK){
WOLFSSL_MSG("Error CRYS_HASH_Finish failed");
return ret;
}
XMEMCPY(sha256->digest, hashResult, WC_SHA256_DIGEST_SIZE);
XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
/* reset state */
return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID);
}
void wc_Sha256Free(wc_Sha256* sha256)
{
if (sha256 == NULL)
return;
}
#endif /* !NO_SHA256 && WOLFSSL_CRYPTOCELL */
#endif /* WOLFSSL_CRYPTOCELL_HASH_C */

View file

@ -1,94 +0,0 @@
# Microchip/Atmel ATECC508A/ATECC608A Support
Support for ATECC508A using these methods:
* TLS: Using the PK callbacks and reference ATECC508A callbacks. See Coding section below. Requires options `HAVE_PK_CALLBACKS` and `WOLFSSL_ATECC_PKCB or WOLFSSL_ATECC508A`
* wolfCrypt: Native wc_ecc_* API's using the `./configure CFLAGS="-DWOLFSSL_ATECC508A"` or `#define WOLFSSL_ATECC508A`.
## Dependency
Requires the Microchip CryptoAuthLib. The examples in `wolfcrypt/src/port/atmel/atmel.c` make calls to the `atcatls_*` API's.
## Building
### Build Options
* `HAVE_PK_CALLBACKS`: Option for enabling wolfSSL's PK callback support for TLS.
* `WOLFSSL_ATECC508A`: Enables support for initializing the CryptoAuthLib and setting up the encryption key used for the I2C communication.
* `WOLFSSL_ATECC_PKCB`: Enables support for the reference PK callbacks without init.
* `WOLFSSL_ATMEL`: Enables ASF hooks seeding random data using the `atmel_get_random_number` function.
* `WOLFSSL_ATMEL_TIME`: Enables the built-in `atmel_get_curr_time_and_date` function get getting time from ASF RTC.
* `ATECC_GET_ENC_KEY`: Macro to define your own function for getting the encryption key.
* `ATECC_SLOT_I2C_ENC`: Macro for the default encryption key slot. Can also get via the slot callback with `ATMEL_SLOT_ENCKEY`.
* `ATECC_MAX_SLOT`: Macro for the maximum dynamically allocated slots.
### Build Command Examples
`./configure --enable-pkcallbacks CFLAGS="-DWOLFSSL_ATECC_PKCB"`
`#define HAVE_PK_CALLBACKS`
`#define WOLFSSL_ATECC_PKCB`
or
`./configure CFLAGS="-DWOLFSSL_ATECC508A"`
`#define WOLFSSL_ATECC508A`
## Coding
Setup the PK callbacks for TLS using:
```
/* Setup PK Callbacks for ATECC508A */
WOLFSSL_CTX* ctx;
wolfSSL_CTX_SetEccKeyGenCb(ctx, atcatls_create_key_cb);
wolfSSL_CTX_SetEccVerifyCb(ctx, atcatls_verify_signature_cb);
wolfSSL_CTX_SetEccSignCb(ctx, atcatls_sign_certificate_cb);
wolfSSL_CTX_SetEccSharedSecretCb(ctx, atcatls_create_pms_cb);
```
The reference ATECC508A PK callback functions are located in the `wolfcrypt/src/port/atmel/atmel.c` file.
Adding a custom context to the callbacks:
```
/* Setup PK Callbacks context */
WOLFSSL* ssl;
void* myOwnCtx;
wolfSSL_SetEccKeyGenCtx(ssl, myOwnCtx);
wolfSSL_SetEccVerifyCtx(ssl, myOwnCtx);
wolfSSL_SetEccSignCtx(ssl, myOwnCtx);
wolfSSL_SetEccSharedSecretCtx(ssl, myOwnCtx);
```
## Benchmarks
Supports ECC SECP256R1 (NIST P-256)
### TLS
TLS Establishment Times:
* Hardware accelerated ATECC508A: 2.342 seconds average
* Software only: 13.422 seconds average
The TLS connection establishment time is 5.73 times faster with the ATECC508A.
### Cryptographic ECC
Software only implementation (SAMD21 48Mhz Cortex-M0, Fast Math TFM-ASM):
`EC-DHE key generation 3123.000 milliseconds, avg over 5 iterations, 1.601 ops/sec`
`EC-DHE key agreement 3117.000 milliseconds, avg over 5 iterations, 1.604 ops/sec`
`EC-DSA sign time 1997.000 milliseconds, avg over 5 iterations, 2.504 ops/sec`
`EC-DSA verify time 5057.000 milliseconds, avg over 5 iterations, 0.988 ops/sec`
ATECC508A HW accelerated implementation:
`EC-DHE key generation 144.400 milliseconds, avg over 5 iterations, 34.722 ops/sec`
`EC-DHE key agreement 134.200 milliseconds, avg over 5 iterations, 37.313 ops/sec`
`EC-DSA sign time 293.400 milliseconds, avg over 5 iterations, 17.065 ops/sec`
`EC-DSA verify time 208.400 milliseconds, avg over 5 iterations, 24.038 ops/sec`
For details see our [wolfSSL Atmel ATECC508A](https://wolfssl.com/wolfSSL/wolfssl-atmel.html) page.

View file

@ -1,843 +0,0 @@
/* atmel.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC_PKCB)
#include <wolfssl/wolfcrypt/memory.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/ssl.h>
#include <wolfssl/internal.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifdef WOLFSSL_ATMEL
/* remap name conflicts */
#define Aes Aes_Remap
#define Gmac Gmac_Remap
#include "asf.h"
#undef Aes
#undef Gmac
#endif /* WOLFSSL_ATMEL */
#include <wolfssl/wolfcrypt/port/atmel/atmel.h>
#ifdef WOLFSSL_ATECC508A
#ifdef WOLFSSL_ATECC508A_TLS
extern ATCA_STATUS device_init_default(void);
#endif
static int mAtcaInitDone = 0;
/* ATECC slotId handling */
static atmel_slot_alloc_cb mSlotAlloc;
static atmel_slot_dealloc_cb mSlotDealloc;
static byte mSlotList[ATECC_MAX_SLOT];
#ifndef SINGLE_THREADED
static wolfSSL_Mutex mSlotMutex;
#endif
/* Raspberry Pi uses /dev/i2c-1 */
#ifndef ATECC_I2C_ADDR
#define ATECC_I2C_ADDR 0xC0
#endif
#ifndef ATECC_I2C_BUS
#define ATECC_I2C_BUS 1
#endif
#ifndef ATECC_DEV_TYPE
#define ATECC_DEV_TYPE ATECC508A
#endif
static ATCAIfaceCfg cfg_ateccx08a_i2c_pi;
#endif /* WOLFSSL_ATECC508A */
/**
* \brief Generate random number to be used for hash.
*/
int atmel_get_random_number(uint32_t count, uint8_t* rand_out)
{
int ret = 0;
#ifdef WOLFSSL_ATECC508A
uint8_t i = 0;
uint32_t copy_count = 0;
uint8_t rng_buffer[RANDOM_NUM_SIZE];
if (rand_out == NULL) {
return -1;
}
while (i < count) {
ret = atcab_random(rng_buffer);
if (ret != ATCA_SUCCESS) {
WOLFSSL_MSG("Failed to create random number!");
return -1;
}
copy_count = (count - i > RANDOM_NUM_SIZE) ? RANDOM_NUM_SIZE : count - i;
XMEMCPY(&rand_out[i], rng_buffer, copy_count);
i += copy_count;
}
#ifdef ATCAPRINTF
atcab_printbin_label((const char*)"\r\nRandom Number", rand_out, count);
#endif
#else
/* TODO: Use on-board TRNG */
#endif
return ret;
}
int atmel_get_random_block(unsigned char* output, unsigned int sz)
{
return atmel_get_random_number((uint32_t)sz, (uint8_t*)output);
}
#if defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME)
#include "asf.h"
#include "rtc_calendar.h"
extern struct rtc_module *_rtc_instance[RTC_INST_NUM];
long atmel_get_curr_time_and_date(long* tm)
{
long rt = 0;
/* Get current time */
struct rtc_calendar_time rtcTime;
const int monthDay[] = {0,31,59,90,120,151,181,212,243,273,304,334};
int month, year, yearLeap;
rtc_calendar_get_time(_rtc_instance[0], &rtcTime);
/* Convert rtc_calendar_time to seconds since UTC */
month = rtcTime.month % 12;
year = rtcTime.year + rtcTime.month / 12;
if (month < 0) {
month += 12;
year--;
}
yearLeap = (month > 1) ? year + 1 : year;
rt = rtcTime.second
+ 60 * (rtcTime.minute
+ 60 * (rtcTime.hour
+ 24 * (monthDay[month] + rtcTime.day - 1
+ 365 * (year - 70)
+ (yearLeap - 69) / 4
- (yearLeap - 1) / 100
+ (yearLeap + 299) / 400
)
)
);
(void)tm;
return rt;
}
#endif
#ifdef WOLFSSL_ATECC508A
int atmel_ecc_translate_err(int status)
{
switch (status) {
case ATCA_SUCCESS:
return 0;
case ATCA_BAD_PARAM:
return BAD_FUNC_ARG;
case ATCA_ALLOC_FAILURE:
return MEMORY_E;
default:
#ifdef WOLFSSL_ATECC508A_DEBUG
printf("ATECC Failure: %x\n", (word32)status);
#endif
break;
}
return WC_HW_E;
}
/* Function to set the slotId allocator and deallocator */
int atmel_set_slot_allocator(atmel_slot_alloc_cb alloc,
atmel_slot_dealloc_cb dealloc)
{
#ifndef SINGLE_THREADED
wc_LockMutex(&mSlotMutex);
#endif
mSlotAlloc = alloc;
mSlotDealloc = dealloc;
#ifndef SINGLE_THREADED
wc_UnLockMutex(&mSlotMutex);
#endif
return 0;
}
/* Function to allocate new slotId number */
int atmel_ecc_alloc(int slotType)
{
int slotId = ATECC_INVALID_SLOT, i;
#ifndef SINGLE_THREADED
wc_LockMutex(&mSlotMutex);
#endif
if (mSlotAlloc) {
slotId = mSlotAlloc(slotType);
}
else {
switch (slotType) {
case ATMEL_SLOT_ENCKEY:
/* not reserved in mSlotList, so return */
slotId = ATECC_SLOT_I2C_ENC;
goto exit;
case ATMEL_SLOT_DEVICE:
/* not reserved in mSlotList, so return */
slotId = ATECC_SLOT_AUTH_PRIV;
goto exit;
case ATMEL_SLOT_ECDHE:
slotId = ATECC_SLOT_ECDHE_PRIV;
break;
case ATMEL_SLOT_ECDHE_ENC:
slotId = ATECC_SLOT_ENC_PARENT;
break;
case ATMEL_SLOT_ANY:
for (i=0; i < ATECC_MAX_SLOT; i++) {
/* Find free slotId */
if (mSlotList[i] == ATECC_INVALID_SLOT) {
slotId = i;
break;
}
}
break;
}
/* is slot available */
if (mSlotList[slotId] != ATECC_INVALID_SLOT) {
slotId = ATECC_INVALID_SLOT;
}
else {
mSlotList[slotId] = slotId;
}
}
exit:
#ifndef SINGLE_THREADED
wc_UnLockMutex(&mSlotMutex);
#endif
return slotId;
}
/* Function to return slotId number to available list */
void atmel_ecc_free(int slotId)
{
#ifndef SINGLE_THREADED
wc_LockMutex(&mSlotMutex);
#endif
if (mSlotDealloc) {
mSlotDealloc(slotId);
}
else if (slotId >= 0 && slotId < ATECC_MAX_SLOT) {
if (slotId != ATECC_SLOT_AUTH_PRIV && slotId != ATECC_SLOT_I2C_ENC) {
/* Mark slotId free */
mSlotList[slotId] = ATECC_INVALID_SLOT;
}
}
#ifndef SINGLE_THREADED
wc_UnLockMutex(&mSlotMutex);
#endif
}
/**
* \brief Callback function for getting the current encryption key
*/
int atmel_get_enc_key_default(byte* enckey, word16 keysize)
{
if (enckey == NULL || keysize != ATECC_KEY_SIZE) {
return BAD_FUNC_ARG;
}
XMEMSET(enckey, 0xFF, keysize); /* use default value */
return 0;
}
/**
* \brief Write enc key before.
*/
static int atmel_init_enc_key(void)
{
int ret;
uint8_t read_key[ATECC_KEY_SIZE];
uint8_t writeBlock = 0;
uint8_t writeOffset = 0;
int slotId;
slotId = atmel_ecc_alloc(ATMEL_SLOT_ENCKEY);
/* check for encryption key slotId */
if (slotId == ATECC_INVALID_SLOT)
return BAD_FUNC_ARG;
/* get encryption key */
ATECC_GET_ENC_KEY(read_key, sizeof(read_key));
ret = atcab_write_zone(ATCA_ZONE_DATA, slotId, writeBlock, writeOffset,
read_key, ATCA_BLOCK_SIZE);
ForceZero(read_key, sizeof(read_key));
ret = atmel_ecc_translate_err(ret);
return ret;
}
int atmel_get_rev_info(word32* revision)
{
int ret;
ret = atcab_info((uint8_t*)revision);
ret = atmel_ecc_translate_err(ret);
return ret;
}
void atmel_show_rev_info(void)
{
#ifdef WOLFSSL_ATECC508A_DEBUG
word32 revision = 0;
atmel_get_rev_info(&revision);
printf("ATECC508A Revision: %x\n", (word32)revision);
#endif
}
int atmel_ecc_create_pms(int slotId, const uint8_t* peerKey, uint8_t* pms)
{
int ret;
uint8_t read_key[ATECC_KEY_SIZE];
int slotIdEnc;
slotIdEnc = atmel_ecc_alloc(ATMEL_SLOT_ECDHE_ENC);
if (slotIdEnc == ATECC_INVALID_SLOT)
return BAD_FUNC_ARG;
/* get encryption key */
ATECC_GET_ENC_KEY(read_key, sizeof(read_key));
/* send the encrypted version of the ECDH command */
ret = atcab_ecdh_enc(slotId, peerKey, pms, read_key, slotIdEnc);
ret = atmel_ecc_translate_err(ret);
/* free the ECDHE slot */
atmel_ecc_free(slotIdEnc);
return ret;
}
int atmel_ecc_create_key(int slotId, byte* peerKey)
{
int ret;
/* verify provided slotId */
if (slotId == ATECC_INVALID_SLOT) {
return WC_HW_WAIT_E;
}
/* generate new ephemeral key on device */
ret = atcab_genkey(slotId, peerKey);
ret = atmel_ecc_translate_err(ret);
return ret;
}
int atmel_ecc_sign(int slotId, const byte* message, byte* signature)
{
int ret;
ret = atcab_sign(slotId, message, signature);
ret = atmel_ecc_translate_err(ret);
return ret;
}
int atmel_ecc_verify(const byte* message, const byte* signature,
const byte* pubkey, int* verified)
{
int ret;
ret = atcab_verify_extern(message, signature, pubkey, (bool*)verified);
ret = atmel_ecc_translate_err(ret);
return ret;
}
#endif /* WOLFSSL_ATECC508A */
int atmel_init(void)
{
int ret = 0;
#ifdef WOLFSSL_ATECC508A
if (!mAtcaInitDone) {
ATCA_STATUS status;
int i;
#ifndef SINGLE_THREADED
wc_InitMutex(&mSlotMutex);
#endif
/* Init the free slotId list */
for (i=0; i<ATECC_MAX_SLOT; i++) {
if (i == ATECC_SLOT_AUTH_PRIV || i == ATECC_SLOT_I2C_ENC) {
mSlotList[i] = i;
}
else {
/* ECC Slots (mark avail) */
mSlotList[i] = ATECC_INVALID_SLOT;
}
}
/* Setup the hardware interface */
XMEMSET(&cfg_ateccx08a_i2c_pi, 0, sizeof(cfg_ateccx08a_i2c_pi));
cfg_ateccx08a_i2c_pi.iface_type = ATCA_I2C_IFACE;
cfg_ateccx08a_i2c_pi.devtype = ATECC_DEV_TYPE;
cfg_ateccx08a_i2c_pi.atcai2c.slave_address = ATECC_I2C_ADDR;
cfg_ateccx08a_i2c_pi.atcai2c.bus = ATECC_I2C_BUS;
cfg_ateccx08a_i2c_pi.atcai2c.baud = 400000;
cfg_ateccx08a_i2c_pi.wake_delay = 1500;
cfg_ateccx08a_i2c_pi.rx_retries = 20;
/* Initialize the CryptoAuthLib to communicate with ATECC508A */
status = atcab_init(&cfg_ateccx08a_i2c_pi);
if (status != ATCA_SUCCESS) {
WOLFSSL_MSG("Failed to initialize atcab");
return WC_HW_E;
}
/* show revision information */
atmel_show_rev_info();
#ifdef WOLFSSL_ATECC508A_TLS
/* Configure the ECC508 for use with TLS API functions */
device_init_default();
#endif
/* Init the I2C pipe encryption key. */
/* Value is generated/stored during pair for the ATECC508A and stored
on micro flash */
/* For this example its a fixed value */
if (atmel_init_enc_key() != 0) {
WOLFSSL_MSG("Failed to initialize transport key");
return WC_HW_E;
}
mAtcaInitDone = 1;
}
#endif /* WOLFSSL_ATECC508A */
return ret;
}
void atmel_finish(void)
{
#ifdef WOLFSSL_ATECC508A
if (mAtcaInitDone) {
atcab_release();
#ifndef SINGLE_THREADED
wc_FreeMutex(&mSlotMutex);
#endif
mAtcaInitDone = 0;
}
#endif
}
/* Reference PK Callbacks */
#ifdef HAVE_PK_CALLBACKS
/**
* \brief Used on the server-side only for creating the ephemeral key for ECDH
*/
int atcatls_create_key_cb(WOLFSSL* ssl, ecc_key* key, unsigned int keySz,
int ecc_curve, void* ctx)
{
int ret;
uint8_t peerKey[ATECC_PUBKEY_SIZE];
uint8_t* qx = &peerKey[0];
uint8_t* qy = &peerKey[ATECC_PUBKEY_SIZE/2];
int slotId;
(void)ssl;
(void)ctx;
/* ATECC508A only supports P-256 */
if (ecc_curve == ECC_SECP256R1) {
slotId = atmel_ecc_alloc(ATMEL_SLOT_ECDHE);
if (slotId == ATECC_INVALID_SLOT)
return WC_HW_WAIT_E;
/* generate new ephemeral key on device */
ret = atmel_ecc_create_key(slotId, peerKey);
/* load generated ECC508A public key into key, used by wolfSSL */
if (ret == 0) {
ret = wc_ecc_import_unsigned(key, qx, qy, NULL, ECC_SECP256R1);
}
if (ret == 0) {
key->slot = slotId;
}
else {
atmel_ecc_free(slotId);
#ifdef WOLFSSL_ATECC508A_DEBUG
printf("atcatls_create_key_cb: ret %d\n", ret);
#endif
}
}
else {
#ifndef WOLFSSL_ATECC508A_NOSOFTECC
/* use software for non P-256 cases */
WC_RNG rng;
ret = wc_InitRng(&rng);
if (ret == 0) {
ret = wc_ecc_make_key_ex(&rng, keySz, key, ecc_curve);
wc_FreeRng(&rng);
}
#else
ret = NOT_COMPILED_IN;
#endif /* !WOLFSSL_ATECC508A_NOSOFTECC */
}
return ret;
}
/**
* \brief Creates a shared secret using a peer public key and a device key
*/
int atcatls_create_pms_cb(WOLFSSL* ssl, ecc_key* otherKey,
unsigned char* pubKeyDer, word32* pubKeySz,
unsigned char* out, word32* outlen,
int side, void* ctx)
{
int ret;
ecc_key tmpKey;
uint8_t peerKeyBuf[ATECC_PUBKEY_SIZE];
uint8_t* peerKey = peerKeyBuf;
uint8_t* qx = &peerKey[0];
uint8_t* qy = &peerKey[ATECC_PUBKEY_SIZE/2];
word32 qxLen = ATECC_PUBKEY_SIZE/2, qyLen = ATECC_PUBKEY_SIZE/2;
if (pubKeyDer == NULL || pubKeySz == NULL || out == NULL || outlen == NULL) {
return BAD_FUNC_ARG;
}
(void)ssl;
(void)ctx;
(void)otherKey;
ret = wc_ecc_init(&tmpKey);
if (ret != 0) {
return ret;
}
/* ATECC508A only supports P-256 */
if (otherKey->dp->id == ECC_SECP256R1) {
XMEMSET(peerKey, 0, ATECC_PUBKEY_SIZE);
/* for client: create and export public key */
if (side == WOLFSSL_CLIENT_END) {
int slotId = atmel_ecc_alloc(ATMEL_SLOT_ECDHE);
if (slotId == ATECC_INVALID_SLOT)
return WC_HW_WAIT_E;
tmpKey.slot = slotId;
/* generate new ephemeral key on device */
ret = atmel_ecc_create_key(slotId, peerKey);
if (ret != ATCA_SUCCESS) {
goto exit;
}
/* convert raw unsigned public key to X.963 format for TLS */
ret = wc_ecc_import_unsigned(&tmpKey, qx, qy, NULL, ECC_SECP256R1);
if (ret == 0) {
ret = wc_ecc_export_x963(&tmpKey, pubKeyDer, pubKeySz);
}
/* export peer's key as raw unsigned for hardware */
if (ret == 0) {
ret = wc_ecc_export_public_raw(otherKey, qx, &qxLen, qy, &qyLen);
}
}
/* for server: import public key */
else if (side == WOLFSSL_SERVER_END) {
tmpKey.slot = otherKey->slot;
/* import peer's key and export as raw unsigned for hardware */
ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &tmpKey, ECC_SECP256R1);
if (ret == 0) {
ret = wc_ecc_export_public_raw(&tmpKey, qx, &qxLen, qy, &qyLen);
}
}
else {
ret = BAD_FUNC_ARG;
}
if (ret != 0) {
goto exit;
}
ret = atmel_ecc_create_pms(tmpKey.slot, peerKey, out);
*outlen = ATECC_KEY_SIZE;
#ifndef WOLFSSL_ATECC508A_NOIDLE
/* put chip into idle to prevent watchdog situation on chip */
atcab_idle();
#endif
(void)qxLen;
(void)qyLen;
}
else {
#ifndef WOLFSSL_ATECC508A_NOSOFTECC
/* use software for non P-256 cases */
ecc_key* privKey = NULL;
ecc_key* pubKey = NULL;
/* for client: create and export public key */
if (side == WOLFSSL_CLIENT_END)
{
WC_RNG rng;
privKey = &tmpKey;
pubKey = otherKey;
ret = wc_InitRng(&rng);
if (ret == 0) {
ret = wc_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id);
if (ret == 0) {
ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz);
}
wc_FreeRng(&rng);
}
}
/* for server: import public key */
else if (side == WOLFSSL_SERVER_END) {
privKey = otherKey;
pubKey = &tmpKey;
ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, pubKey,
otherKey->dp->id);
}
else {
ret = BAD_FUNC_ARG;
}
/* generate shared secret and return it */
if (ret == 0) {
ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen);
}
#else
ret = NOT_COMPILED_IN;
#endif /* !WOLFSSL_ATECC508A_NOSOFTECC */
}
exit:
wc_ecc_free(&tmpKey);
#ifdef WOLFSSL_ATECC508A_DEBUG
if (ret != 0) {
printf("atcab_ecdh_enc: ret %d\n", ret);
}
#endif
return ret;
}
/**
* \brief Sign received digest using private key on device
*/
int atcatls_sign_certificate_cb(WOLFSSL* ssl, const byte* in, unsigned int inSz,
byte* out, word32* outSz, const byte* key, unsigned int keySz, void* ctx)
{
int ret;
byte sigRs[ATECC_SIG_SIZE];
int slotId;
(void)ssl;
(void)inSz;
(void)key;
(void)keySz;
(void)ctx;
if (in == NULL || out == NULL || outSz == NULL) {
return BAD_FUNC_ARG;
}
slotId = atmel_ecc_alloc(ATMEL_SLOT_DEVICE);
if (slotId == ATECC_INVALID_SLOT)
return WC_HW_WAIT_E;
/* We can only sign with P-256 */
ret = atmel_ecc_sign(slotId, in, sigRs);
if (ret != ATCA_SUCCESS) {
ret = WC_HW_E; goto exit;
}
#ifndef WOLFSSL_ATECC508A_NOIDLE
/* put chip into idle to prevent watchdog situation on chip */
atcab_idle();
#endif
/* Encode with ECDSA signature */
ret = wc_ecc_rs_raw_to_sig(
&sigRs[0], ATECC_SIG_SIZE/2,
&sigRs[ATECC_SIG_SIZE/2], ATECC_SIG_SIZE/2,
out, outSz);
if (ret != 0) {
goto exit;
}
exit:
atmel_ecc_free(slotId);
#ifdef WOLFSSL_ATECC508A_DEBUG
if (ret != 0) {
printf("atcatls_sign_certificate_cb: ret %d\n", ret);
}
#endif
return ret;
}
/**
* \brief Verify signature received from peers to prove peer's private key.
*/
int atcatls_verify_signature_cb(WOLFSSL* ssl, const byte* sig, unsigned int sigSz,
const byte* hash, unsigned int hashSz, const byte* key, unsigned int keySz, int* result,
void* ctx)
{
int ret;
ecc_key tmpKey;
word32 idx = 0;
uint8_t peerKey[ATECC_PUBKEY_SIZE];
uint8_t* qx = &peerKey[0];
uint8_t* qy = &peerKey[ATECC_PUBKEY_SIZE/2];
word32 qxLen = ATECC_PUBKEY_SIZE/2, qyLen = ATECC_PUBKEY_SIZE/2;
byte sigRs[ATECC_SIG_SIZE];
word32 rSz = ATECC_SIG_SIZE/2;
word32 sSz = ATECC_SIG_SIZE/2;
(void)sigSz;
(void)hashSz;
(void)ctx;
if (ssl == NULL || key == NULL || sig == NULL || hash == NULL || result == NULL) {
return BAD_FUNC_ARG;
}
/* import public key */
ret = wc_ecc_init(&tmpKey);
if (ret == 0) {
ret = wc_EccPublicKeyDecode(key, &idx, &tmpKey, keySz);
}
if (ret != 0) {
goto exit;
}
if (tmpKey.dp->id == ECC_SECP256R1) {
/* export public as unsigned bin for hardware */
ret = wc_ecc_export_public_raw(&tmpKey, qx, &qxLen, qy, &qyLen);
wc_ecc_free(&tmpKey);
if (ret != 0) {
goto exit;
}
/* decode the ECDSA signature */
ret = wc_ecc_sig_to_rs(sig, sigSz,
&sigRs[0], &rSz,
&sigRs[ATECC_SIG_SIZE/2], &sSz);
if (ret != 0) {
goto exit;
}
ret = atmel_ecc_verify(hash, sigRs, peerKey, result);
if (ret != ATCA_SUCCESS || !*result) {
ret = WC_HW_E; goto exit;
}
#ifndef WOLFSSL_ATECC508A_NOIDLE
/* put chip into idle to prevent watchdog situation on chip */
atcab_idle();
#endif
}
else {
#ifndef WOLFSSL_ATECC508A_NOSOFTECC
ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &tmpKey);
#else
ret = NOT_COMPILED_IN;
#endif /* !WOLFSSL_ATECC508A_NOSOFTECC */
}
(void)rSz;
(void)sSz;
(void)qxLen;
(void)qyLen;
ret = 0; /* success */
exit:
#ifdef WOLFSSL_ATECC508A_DEBUG
if (ret != 0) {
printf("atcatls_verify_signature_cb: ret %d\n", ret);
}
#endif
return ret;
}
int atcatls_set_callbacks(WOLFSSL_CTX* ctx)
{
wolfSSL_CTX_SetEccKeyGenCb(ctx, atcatls_create_key_cb);
wolfSSL_CTX_SetEccVerifyCb(ctx, atcatls_verify_signature_cb);
wolfSSL_CTX_SetEccSignCb(ctx, atcatls_sign_certificate_cb);
wolfSSL_CTX_SetEccSharedSecretCb(ctx, atcatls_create_pms_cb);
return 0;
}
int atcatls_set_callback_ctx(WOLFSSL* ssl, void* user_ctx)
{
wolfSSL_SetEccKeyGenCtx(ssl, user_ctx);
wolfSSL_SetEccVerifyCtx(ssl, user_ctx);
wolfSSL_SetEccSignCtx(ssl, user_ctx);
wolfSSL_SetEccSharedSecretCtx(ssl, user_ctx);
return 0;
}
#endif /* HAVE_PK_CALLBACKS */
#endif /* WOLFSSL_ATMEL || WOLFSSL_ATECC508A || WOLFSSL_ATECC_PKCB */

View file

@ -1,649 +0,0 @@
/* caam_aes.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_AES) && \
!defined(NO_IMX6_CAAM_AES)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/aes.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
int wc_AesSetKey(Aes* aes, const byte* key, word32 len,
const byte* iv, int dir)
{
int ret;
if (aes == NULL || key == NULL) {
return BAD_FUNC_ARG;
}
if (len > 32) {
byte out[32]; /* max AES key size */
word32 outSz;
int ret;
if (len != 64 && len != 72 && len != 80) {
return BAD_FUNC_ARG;
}
outSz = sizeof(out);
/* if length greater then 32 then try to unencapsulate */
if ((ret = wc_caamOpenBlob((byte*)key, len, out, &outSz)) != 0) {
return ret;
}
XMEMCPY((byte*)aes->key, out, outSz);
aes->keylen = outSz;
}
else {
if (len != 16 && len != 24 && len != 32) {
return BAD_FUNC_ARG;
}
XMEMCPY((byte*)aes->key, key, len);
aes->keylen = len;
}
switch (aes->keylen) {
case 16: aes->rounds = 10; break;
case 24: aes->rounds = 12; break;
case 32: aes->rounds = 14; break;
default:
return BAD_FUNC_ARG;
}
if ((ret = wc_AesSetIV(aes, iv)) != 0) {
return ret;
}
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif
return 0;
}
int wc_AesCbcEncrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
word32 blocks;
WOLFSSL_ENTER("wc_AesCbcEncrypt");
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if (blocks > 0) {
Buffer buf[4];
word32 arg[4];
word32 keySz;
int ret;
if (wc_AesGetKeySize(aes, &keySz) != 0) {
return BAD_FUNC_ARG;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)aes->reg;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)in;
buf[2].Length = blocks * AES_BLOCK_SIZE;
buf[3].BufferType = DataBuffer | LastBuffer;
buf[3].TheAddress = (Address)out;
buf[3].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) {
WOLFSSL_MSG("Error with CAAM AES CBC encrypt");
return ret;
}
}
return 0;
}
int wc_AesCbcDecrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
word32 blocks;
WOLFSSL_ENTER("wc_AesCbcDecrypt");
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if (blocks > 0) {
Buffer buf[4];
word32 arg[4];
word32 keySz;
int ret;
if (wc_AesGetKeySize(aes, &keySz) != 0) {
return BAD_FUNC_ARG;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)aes->reg;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)in;
buf[2].Length = blocks * AES_BLOCK_SIZE;
buf[3].BufferType = DataBuffer | LastBuffer;
buf[3].TheAddress = (Address)out;
buf[3].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_DEC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCBC)) != 0) {
WOLFSSL_MSG("Error with CAAM AES CBC decrypt");
return ret;
}
}
return 0;
}
#if defined(HAVE_AES_ECB)
/* is assumed that input size is a multiple of AES_BLOCK_SIZE */
int wc_AesEcbEncrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
word32 blocks;
Buffer buf[3];
word32 arg[4];
word32 keySz;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if (wc_AesGetKeySize(aes, &keySz) != 0) {
return BAD_FUNC_ARG;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)in;
buf[1].Length = blocks * AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer | LastBuffer;
buf[2].TheAddress = (Address)out;
buf[2].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESECB)) != 0) {
WOLFSSL_MSG("Error with CAAM AES ECB encrypt");
return ret;
}
return 0;
}
int wc_AesEcbDecrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
word32 blocks;
Buffer buf[3];
word32 arg[4];
word32 keySz;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
blocks = sz / AES_BLOCK_SIZE;
if (wc_AesGetKeySize(aes, &keySz) != 0) {
return BAD_FUNC_ARG;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)in;
buf[1].Length = blocks * AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer | LastBuffer;
buf[2].TheAddress = (Address)out;
buf[2].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_DEC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESECB)) != 0) {
WOLFSSL_MSG("Error with CAAM AES ECB decrypt");
return ret;
}
return 0;
}
#endif
/* AES-CTR */
#ifdef WOLFSSL_AES_COUNTER
/* Increment AES counter (from wolfcrypt/src/aes.c) */
static WC_INLINE void IncrementAesCounter(byte* inOutCtr)
{
/* in network byte order so start at end and work back */
int i;
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
if (++inOutCtr[i]) /* we're done unless we overflow */
return;
}
}
int wc_AesCtrEncrypt(Aes* aes, byte* out,
const byte* in, word32 sz)
{
byte* tmp;
Buffer buf[4];
word32 arg[4];
word32 keySz;
int ret, blocks;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (wc_AesGetKeySize(aes, &keySz) != 0) {
return BAD_FUNC_ARG;
}
/* consume any unused bytes left in aes->tmp */
tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
while (aes->left && sz) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
sz--;
}
/* do full blocks to then get potential left over amount */
blocks = sz / AES_BLOCK_SIZE;
if (blocks > 0) {
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)aes->reg;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)in;
buf[2].Length = blocks * AES_BLOCK_SIZE;
buf[3].BufferType = DataBuffer | LastBuffer;
buf[3].TheAddress = (Address)out;
buf[3].Length = blocks * AES_BLOCK_SIZE;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = blocks * AES_BLOCK_SIZE;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCTR)) != 0) {
WOLFSSL_MSG("Error with CAAM AES CTR encrypt");
return ret;
}
out += blocks * AES_BLOCK_SIZE;
in += blocks * AES_BLOCK_SIZE;
sz -= blocks * AES_BLOCK_SIZE;
}
if (sz) {
wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg);
IncrementAesCounter((byte*)aes->reg);
aes->left = AES_BLOCK_SIZE;
tmp = (byte*)aes->tmp;
while (sz--) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
}
}
return 0;
}
#endif
/* AES-DIRECT */
#if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER)
void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
{
Buffer buf[3];
word32 arg[4];
word32 keySz;
if (aes == NULL || out == NULL || in == NULL) {
/* return BAD_FUNC_ARG; */
return;
}
if (wc_AesGetKeySize(aes, &keySz) != 0) {
/* return BAD_FUNC_ARG; */
return;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)in;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer | LastBuffer;
buf[2].TheAddress = (Address)out;
buf[2].Length = AES_BLOCK_SIZE;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = AES_BLOCK_SIZE;
if (wc_caamAddAndWait(buf, arg, CAAM_AESECB) != 0) {
WOLFSSL_MSG("Error with CAAM AES direct encrypt");
}
}
void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
{
Buffer buf[3];
word32 arg[4];
word32 keySz;
if (aes == NULL || out == NULL || in == NULL) {
/* return BAD_FUNC_ARG; */
return;
}
if (wc_AesGetKeySize(aes, &keySz) != 0) {
/* return BAD_FUNC_ARG; */
return;
}
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)in;
buf[1].Length = AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer | LastBuffer;
buf[2].TheAddress = (Address)out;
buf[2].Length = AES_BLOCK_SIZE;
arg[0] = CAAM_DEC;
arg[1] = keySz;
arg[2] = AES_BLOCK_SIZE;
if (wc_caamAddAndWait(buf, arg, CAAM_AESECB) != 0) {
WOLFSSL_MSG("Error with CAAM AES direct decrypt");
}
}
int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len,
const byte* iv, int dir)
{
return wc_AesSetKey(aes, key, len, iv, dir);
}
#endif
#ifdef HAVE_AESCCM
int wc_AesCcmEncrypt(Aes* aes, byte* out,
const byte* in, word32 inSz,
const byte* nonce, word32 nonceSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
Buffer buf[5];
word32 arg[4];
word32 keySz;
word32 i;
byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE];
int lenSz;
byte mask = 0xFF;
const word32 wordSz = (word32)sizeof(word32);
int ret;
/* sanity check on arguments */
if (aes == NULL || out == NULL || in == NULL || nonce == NULL
|| authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
authTagSz > AES_BLOCK_SIZE)
return BAD_FUNC_ARG;
if (wc_AesGetKeySize(aes, &keySz) != 0) {
return BAD_FUNC_ARG;
}
/* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */
XMEMCPY(B0Ctr0+1, nonce, nonceSz);
XMEMCPY(B0Ctr0+AES_BLOCK_SIZE+1, nonce, nonceSz);
lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
B0Ctr0[0] = (authInSz > 0 ? 64 : 0)
+ (8 * (((byte)authTagSz - 2) / 2))
+ (lenSz - 1);
for (i = 0; i < lenSz; i++) {
if (mask && i >= wordSz)
mask = 0x00;
B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE - 1 - i] = 0;
}
B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1;
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)B0Ctr0;
buf[1].Length = AES_BLOCK_SIZE + AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)authIn;
buf[2].Length = authInSz;
buf[3].BufferType = DataBuffer;
buf[3].TheAddress = (Address)in;
buf[3].Length = inSz;
buf[4].BufferType = DataBuffer | LastBuffer;
buf[4].TheAddress = (Address)out;
buf[4].Length = inSz;
arg[0] = CAAM_ENC;
arg[1] = keySz;
arg[2] = inSz;
arg[3] = authInSz;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) {
WOLFSSL_MSG("Error with CAAM AES-CCM encrypt");
return ret;
}
XMEMCPY(authTag, B0Ctr0, authTagSz);
return 0;
}
#ifdef HAVE_AES_DECRYPT
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)
{
Buffer buf[5];
word32 arg[4];
word32 keySz;
word32 i;
byte B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE];
byte tag[AES_BLOCK_SIZE];
int lenSz;
byte mask = 0xFF;
const word32 wordSz = (word32)sizeof(word32);
int ret;
/* sanity check on arguments */
if (aes == NULL || out == NULL || in == NULL || nonce == NULL
|| authTag == NULL || nonceSz < 7 || nonceSz > 13 ||
authTagSz > AES_BLOCK_SIZE)
return BAD_FUNC_ARG;
if (wc_AesGetKeySize(aes, &keySz) != 0) {
return BAD_FUNC_ARG;
}
/* set up B0 and CTR0 similar to how wolfcrypt/src/aes.c does */
XMEMCPY(B0Ctr0+1, nonce, nonceSz);
XMEMCPY(B0Ctr0+AES_BLOCK_SIZE+1, nonce, nonceSz);
lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz;
B0Ctr0[0] = (authInSz > 0 ? 64 : 0)
+ (8 * (((byte)authTagSz - 2) / 2))
+ (lenSz - 1);
for (i = 0; i < lenSz; i++) {
if (mask && i >= wordSz)
mask = 0x00;
B0Ctr0[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask;
B0Ctr0[AES_BLOCK_SIZE + AES_BLOCK_SIZE - 1 - i] = 0;
}
B0Ctr0[AES_BLOCK_SIZE] = lenSz - 1;
wc_AesEncryptDirect(aes, tag, B0Ctr0 + AES_BLOCK_SIZE);
/* Set buffers for key, cipher text, and plain text */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)aes->key;
buf[0].Length = keySz;
buf[1].BufferType = DataBuffer;
buf[1].TheAddress = (Address)B0Ctr0;
buf[1].Length = AES_BLOCK_SIZE + AES_BLOCK_SIZE;
buf[2].BufferType = DataBuffer;
buf[2].TheAddress = (Address)authIn;
buf[2].Length = authInSz;
buf[3].BufferType = DataBuffer;
buf[3].TheAddress = (Address)in;
buf[3].Length = inSz;
buf[4].BufferType = DataBuffer | LastBuffer;
buf[4].TheAddress = (Address)out;
buf[4].Length = inSz;
arg[0] = CAAM_DEC;
arg[1] = keySz;
arg[2] = inSz;
arg[3] = authInSz;
if ((ret = wc_caamAddAndWait(buf, arg, CAAM_AESCCM)) != 0) {
WOLFSSL_MSG("Error with CAAM AES-CCM derypt");
return ret;
}
xorbuf(tag, B0Ctr0, authTagSz);
if (ConstantCompare(tag, authTag, authTagSz) != 0) {
/* If the authTag check fails, don't keep the decrypted data.
* Unfortunately, you need the decrypted data to calculate the
* check value. */
XMEMSET(out, 0, inSz);
ret = AES_CCM_AUTH_E;
}
ForceZero(tag, AES_BLOCK_SIZE);
ForceZero(B0Ctr0, AES_BLOCK_SIZE * 2);
return ret;
}
#endif /* HAVE_AES_DECRYPT */
#endif /* HAVE_AESCCM */
#endif /* WOLFSSL_IMX6_CAAM && !NO_AES */

View file

@ -1,289 +0,0 @@
/* caam_init.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \
defined(WOLFSSL_IMX6_CAAM_BLOB)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#define WC_CAAM_BLOB_SZ 48
#ifndef WC_CAAM_PASSWORD
#define WC_CAAM_PASSWORD "!systempassword"
#endif
#if defined(__INTEGRITY) || defined(INTEGRITY)
#include <INTEGRITY.h>
#include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
static IODevice caam = NULLIODevice;
#endif
#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
#include <stdio.h>
#include <wolfssl/version.h>
static void wc_caamBanner(void)
{
printf("********* wolfSSL Version %s : Printing Out CAAM Information ********\n",
LIBWOLFSSL_VERSION_STRING);
printf("CAAM Status [0x%8.8x] = 0x%8.8x\n",
CAAM_STATUS, WC_CAAM_READ(CAAM_STATUS));
printf("CAAM Version MS Register [0x%8.8x] = 0x%8.8x\n",
CAAM_VERSION_MS, WC_CAAM_READ(CAAM_VERSION_MS));
printf("CAAM Version LS Register [0x%8.8x] = 0x%8.8x\n",
CAAM_VERSION_LS, WC_CAAM_READ(CAAM_VERSION_LS));
printf("CAAM Support MS Register [0x%8.8x] = 0x%8.8x\n",
CAMM_SUPPORT_MS, WC_CAAM_READ(CAMM_SUPPORT_MS));
printf("CAAM Support LS [0x%8.8x] = 0x%8.8x\n",
CAMM_SUPPORT_LS, WC_CAAM_READ(CAMM_SUPPORT_LS));
printf("********************************************************************\n\n");
}
#endif
/* Allow runtime setting for CAAM IODevice in case user wants to use password
* at run time.
*
* returns 0 on success
*
* NOTE this is how IODevice is defined in INTEGRITY "typedef struct
* IODeviceStruct *IODevice;"
*/
int wc_caamSetResource(IODevice ioDev)
{
WOLFSSL_MSG("Setting CAAM driver");
caam = ioDev;
return 0;
}
/* Check hardware support
*
* returns 0 on success
*/
int wc_caamInit(void)
{
int ret;
word32 reg;
/* get the driver up */
if (caam == NULLIODevice) {
WOLFSSL_MSG("Starting CAAM driver");
if ((ret = (int)RequestResource((Object *)&caam, "wolfSSL_CAAM_Driver",
WC_CAAM_PASSWORD)) != (int)Success) {
WOLFSSL_MSG("Unable to get the CAAM IODevice, check password?");
WOLFSSL_LEAVE("wc_caamInit: error from driver = ", ret);
ret = 0; /* not a hard failure because user can set resource */
}
}
#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
/* print out CAAM version/info and wolfSSL version */
wc_caamBanner();
#endif
/* check that for implemented modules
* bits 0-3 AES, 4-7 DES, 12-15 Hashing , 16-19 RNG */
reg = WC_CAAM_READ(CAMM_SUPPORT_LS);
#ifndef WC_NO_RNG
if (((reg & 0x000F0000) >> 16) > 0) {
WOLFSSL_MSG("Found CAAM RNG hardware module");
if ((WC_CAAM_READ(CAAM_RTMCTL) & 0x40000001) != 0x40000001) {
WOLFSSL_MSG("Error CAAM RNG has not been set up");
}
}
#endif
#ifndef NO_SHA256
if ((reg & 0x0000F000) > 0) {
WOLFSSL_MSG("Found CAAM MDHA module");
}
else {
WOLFSSL_MSG("Hashing not supported by CAAM");
return WC_HW_E;
}
#endif
#ifndef NO_AES
if ((reg & 0x0000000F) > 0) {
WOLFSSL_MSG("Found CAAM AES module");
}
else {
WOLFSSL_MSG("AES not supported by CAAM");
return WC_HW_E;
}
#endif
(void)ret;
return 0;
}
int wc_caamFree(void)
{
return 0;
}
word32 wc_caamReadRegister(word32 reg)
{
Value out = 0;
if (caam == NULLIODevice) {
WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
return 0;
}
if (ReadIODeviceRegister(caam, reg, &out) != Success) {
WOLFSSL_MSG("Error reading register\n");
}
return (word32)out;
}
void wc_caamWriteRegister(word32 reg, word32 value)
{
if (caam == NULLIODevice) {
WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
return;
}
if (WriteIODeviceRegister(caam, reg, value) != Success) {
WOLFSSL_MSG("Error writing to register\n");
}
}
/* return 0 on success and WC_HW_E on failure. Can also return WC_HW_WAIT_E
* in the case that the driver is waiting for a resource or RAN_BLOCK_E if
* waiting for entropy. */
int wc_caamAddAndWait(Buffer* buf, word32 arg[4], word32 type)
{
int ret;
if (caam == NULLIODevice) {
WOLFSSL_MSG("Error CAAM IODevice not found! Bad password?");
return WC_HW_E;
}
if ((ret = SynchronousSendIORequest(caam, type, (const Value*)arg, buf))
!= Success) {
#if defined(WOLFSSL_CAAM_PRINT) || defined(WOLFSSL_CAAM_DEBUG)
printf("ret of SynchronousSendIORequest = %d type = %d\n", ret, type);
#endif
/* if waiting for resource or RNG return waiting */
if (ret == Waiting) {
WOLFSSL_MSG("Waiting on entropy from driver");
return RAN_BLOCK_E;
}
if (ret == ResourceNotAvailable) {
WOLFSSL_MSG("Waiting on CAAM driver");
return WC_HW_WAIT_E;
}
return WC_HW_E;
}
(void)ret;
return 0;
}
int wc_caamCreateBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
{
Buffer in[3];
word32 arg[4];
int ret;
word32 local[2] = {0,0};
if (data == NULL || out == NULL || outSz == NULL ||
*outSz < dataSz + WC_CAAM_BLOB_SZ) {
return BAD_FUNC_ARG;
}
in[0].BufferType = DataBuffer;
in[0].TheAddress = (Address)local;
in[0].Length = sizeof(local);
in[1].BufferType = DataBuffer;
in[1].TheAddress = (Address)data;
in[1].Length = dataSz;
in[2].BufferType = DataBuffer | LastBuffer;
in[2].TheAddress = (Address)out;
in[2].Length = dataSz + WC_CAAM_BLOB_SZ;
arg[2] = dataSz;
if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_ENCAP)) != 0) {
WOLFSSL_MSG("Error with CAAM blob create");
return ret;
}
*outSz = dataSz + WC_CAAM_BLOB_SZ;
return 0;
}
int wc_caamOpenBlob(byte* data, word32 dataSz, byte* out, word32* outSz)
{
Buffer in[3];
word32 arg[4];
int ret;
word32 local[2] = {0,0};
if (data == NULL || out == NULL || outSz == NULL ||
*outSz < dataSz - WC_CAAM_BLOB_SZ) {
return BAD_FUNC_ARG;
}
in[0].BufferType = DataBuffer;
in[0].TheAddress = (Address)local;
in[0].Length = sizeof(local);
in[0].BufferType = DataBuffer;
in[0].TheAddress = (Address)data;
in[0].Length = dataSz;
in[1].BufferType = DataBuffer | LastBuffer;
in[1].TheAddress = (Address)out;
in[1].Length = dataSz - WC_CAAM_BLOB_SZ;
arg[2] = dataSz;
if ((ret = wc_caamAddAndWait(in, arg, CAAM_BLOB_DECAP)) != 0) {
WOLFSSL_MSG("Error with CAAM blob create");
return ret;
}
*outSz = dataSz - WC_CAAM_BLOB_SZ;
return 0;
}
#endif /* WOLFSSL_IMX6_CAAM */

View file

@ -1,397 +0,0 @@
/* caam_sha.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#include <INTEGRITY.h>
#include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
#include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
#include <stdio.h>
#endif
#ifndef NO_SHA
#include <wolfssl/wolfcrypt/sha.h>
#endif
#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224)
#include <wolfssl/wolfcrypt/sha256.h>
#endif
#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
#include <wolfssl/wolfcrypt/sha512.h>
#endif
#ifndef NO_MD5
#include <wolfssl/wolfcrypt/md5.h>
#endif
/******************************************************************************
Common Code Between SHA Functions
****************************************************************************/
static int _InitSha(wc_Sha* sha, void* heap, int devId, word32 digestSz,
word32 type)
{
Buffer buf[1];
word32 arg[4];
int ret;
(void)heap;
(void)devId;
if (sha == NULL) {
return BAD_FUNC_ARG;
}
XMEMSET(sha, 0, sizeof(Sha));
/* Set buffer for context */
buf[0].BufferType = DataBuffer | LastBuffer;
buf[0].TheAddress = (Address)sha->ctx;
buf[0].Length = digestSz + WC_CAAM_CTXLEN;
buf[0].Transferred = 0;
arg[0] = CAAM_ALG_INIT;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA init");
return ret;
}
return 0;
}
static int _ShaUpdate(wc_Sha* sha, const byte* data, word32 len, word32 digestSz,
word32 type)
{
Buffer buf[2];
word32 arg[4];
int ret;
byte* local;
if (sha == NULL ||(data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
if (len == 0) return 0; /* nothing to do */
local = (byte*)sha->buffer;
/* check for filling out existing buffer */
if (sha->buffLen > 0) {
word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen);
XMEMCPY(&local[sha->buffLen], data, add);
sha->buffLen += add;
data += add;
len -= add;
if (sha->buffLen == WC_CAAM_HASH_BLOCK) {
/* Set buffer for context */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)sha->ctx;
buf[0].Length = digestSz + WC_CAAM_CTXLEN;
buf[0].Transferred = 0;
/* data to update with */
buf[1].BufferType = DataBuffer | LastBuffer;
buf[1].TheAddress = (Address)sha->buffer;
buf[1].Length = sha->buffLen;
buf[1].Transferred = 0;
arg[0] = CAAM_ALG_UPDATE;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA update");
return ret;
}
sha->buffLen = 0; /* cleared out buffer */
}
}
/* check if multiple full blocks can be done */
if (len >= WC_CAAM_HASH_BLOCK) {
word32 sz = len / WC_CAAM_HASH_BLOCK;
sz = sz * WC_CAAM_HASH_BLOCK;
/* Set buffer for context */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)sha->ctx;
buf[0].Length = digestSz + WC_CAAM_CTXLEN;
buf[0].Transferred = 0;
/* data to update with */
buf[1].BufferType = DataBuffer | LastBuffer;
buf[1].TheAddress = (Address)data;
buf[1].Length = sz;
buf[1].Transferred = 0;
arg[0] = CAAM_ALG_UPDATE;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA update");
return ret;
}
len -= sz;
data += sz;
}
/* check for left overs */
if (len > 0) {
word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen);
XMEMCPY(&local[sha->buffLen], data, add);
sha->buffLen += add;
}
return 0;
}
static int _ShaFinal(wc_Sha* sha, byte* out, word32 digestSz,
word32 type)
{
Buffer buf[2];
word32 arg[4];
int ret;
if (sha == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
/* Set buffer for context */
buf[0].BufferType = DataBuffer;
buf[0].TheAddress = (Address)sha->ctx;
buf[0].Length = digestSz + WC_CAAM_CTXLEN;
buf[0].Transferred = 0;
/* add any potential left overs */
buf[1].BufferType = DataBuffer | LastBuffer;
buf[1].TheAddress = (Address)sha->buffer;
buf[1].Length = sha->buffLen;
buf[1].Transferred = 0;
arg[0] = CAAM_ALG_FINAL;
arg[1] = digestSz + WC_CAAM_CTXLEN;
if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
WOLFSSL_MSG("Error with CAAM SHA init");
return ret;
}
return 0;
}
/******************************************************************************
MD5
****************************************************************************/
#if !defined(NO_MD5)
int wc_InitMd5_ex(wc_Md5* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, MD5_DIGEST_SIZE, CAAM_MD5);
}
int wc_Md5Update(wc_Md5* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, MD5_DIGEST_SIZE, CAAM_MD5);
}
int wc_Md5Final(wc_Md5* sha, byte* hash)
{
int ret;
if ((ret = _ShaFinal(sha, hash, MD5_DIGEST_SIZE, CAAM_MD5)) != 0) {
return ret;
}
XMEMCPY(hash, (byte*)sha->ctx, MD5_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, MD5_DIGEST_SIZE, CAAM_MD5);
}
#endif /* !NO_MD5 */
/******************************************************************************
SHA 1
****************************************************************************/
#if !defined(NO_SHA)
int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA_DIGEST_SIZE, CAAM_SHA);
}
int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA_DIGEST_SIZE, CAAM_SHA);
}
int wc_ShaFinal(wc_Sha* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA_DIGEST_SIZE, CAAM_SHA)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA_DIGEST_SIZE, CAAM_SHA);
}
#endif /* !NO_SHA */
/******************************************************************************
SHA 224
****************************************************************************/
#ifdef WOLFSSL_SHA224
int wc_InitSha224_ex(wc_Sha224* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA224);
}
int wc_Sha224Update(wc_Sha224* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA224);
}
int wc_Sha224Final(wc_Sha224* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA224)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA224_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA224);
}
#endif /* WOLFSSL_SHA224 */
/******************************************************************************
SHA 256
****************************************************************************/
#if !defined(NO_SHA256)
int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA256);
}
int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA256);
}
int wc_Sha256Final(wc_Sha256* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA256)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA256_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA256);
}
#endif /* !NO_SHA256 */
/******************************************************************************
SHA 384
****************************************************************************/
#ifdef WOLFSSL_SHA384
int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA384);
}
int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA384);
}
int wc_Sha384Final(wc_Sha384* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA384)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA384_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA384);
}
#endif /* WOLFSSL_SHA384 */
/******************************************************************************
SHA 512
****************************************************************************/
#ifdef WOLFSSL_SHA512
int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId)
{
return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA512);
}
int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len)
{
return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA512);
}
int wc_Sha512Final(wc_Sha512* sha, byte* out)
{
int ret;
if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA512)) != 0) {
return ret;
}
XMEMCPY(out, (byte*)sha->ctx, SHA512_DIGEST_SIZE);
return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA512);
}
#endif /* WOLFSSL_SHA512 */
#endif /* WOLFSSL_IMX6_CAAM */

View file

@ -1,3 +0,0 @@
# Cavium Nitrox III/V Support
Please contact wolfSSL at info@wolfssl.com to request an evaluation.

View file

@ -1,3 +0,0 @@
# Cavium Octeon III CN7300
Please contact wolfSSL at info@wolfssl.com to request an evaluation.

View file

@ -1,879 +0,0 @@
/* cavium_octeon_sync.c
*
* Copyright(C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.(formerly known as CyaSSL)
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
*(at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#ifdef HAVE_CAVIUM_OCTEON_SYNC
/* Setting NO_MAIN_DRIVER here because this file ends up building
* in the library sources which doesn't have NO_MAIN_DRIVER set,
* as the library expects main to be somewhere else. */
#undef NO_MAIN_DRIVER
#define NO_MAIN_DRIVER
#include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "cvmx.h"
#include "cvmx-asm.h"
#include "cvmx-key.h"
#include "cvmx-swap.h"
#ifndef NO_DES3
#include <wolfssl/wolfcrypt/des3.h>
#endif
#ifndef NO_AES
#include <wolfssl/wolfcrypt/aes.h>
#endif
#define NOOPT __attribute__((optimize("O0")))
static int devId = 1234;
#ifndef NO_DES3
static int Octeon_Des3_CbcEncrypt(Des3* des3,
uint64_t *inp64, uint64_t *outp64, size_t inl)
{
register uint64_t i0, r0;
uint64_t *key, *iv;
if (des3 == NULL || inp64 == NULL || outp64 == NULL)
return BAD_FUNC_ARG;
/* expects 64-bit aligned value */
key = (uint64_t*)des3->devKey;
CVMX_MT_3DES_KEY(key[0], 0);
CVMX_MT_3DES_KEY(key[1], 1);
CVMX_MT_3DES_KEY(key[2], 2);
iv = (uint64_t*)des3->reg;
CVMX_MT_3DES_IV(iv[0]);
CVMX_PREFETCH0(inp64);
i0 = *inp64;
/* DES3 assembly can handle 16-byte chunks */
if (inl >= 16) {
CVMX_MT_3DES_ENC_CBC(i0);
inl -= 8;
inp64++;
outp64++;
if (inl >= 8) {
i0 = inp64[0];
CVMX_MF_3DES_RESULT(r0);
CVMX_MT_3DES_ENC_CBC(i0);
for (;;) {
outp64[-1] = r0;
inl -= 8;
inp64++;
outp64++;
i0 = *inp64;
if (inl < 8)
break;
CVMX_PREFETCH(inp64, 64);
CVMX_MF_3DES_RESULT(r0);
CVMX_MT_3DES_ENC_CBC(i0);
}
}
CVMX_MF_3DES_RESULT(r0);
outp64[-1] = r0;
}
/* remainder */
if (inl > 0) {
uint64_t r = 0;
if (inl <= 8) {
XMEMCPY(&r, inp64, inl);
CVMX_MT_3DES_ENC_CBC(r);
CVMX_MF_3DES_RESULT(*outp64);
}
else {
i0 = *inp64;
CVMX_MT_3DES_ENC_CBC(i0);
CVMX_MF_3DES_RESULT(*outp64);
inp64++, outp64++;
XMEMCPY(&r, inp64, inl);
CVMX_MT_3DES_ENC_CBC(r);
CVMX_MF_3DES_RESULT(*outp64);
}
}
CVMX_MT_3DES_IV(iv[0]);
return 0;
}
static int Octeon_Des3_CbcDecrypt(Des3* des3,
uint64_t *inp64, uint64_t *outp64, size_t inl)
{
register uint64_t i0, r0;
uint64_t *key, *iv;
if (des3 == NULL || inp64 == NULL || outp64 == NULL)
return BAD_FUNC_ARG;
/* expects 64-bit aligned value */
key = (uint64_t*)des3->devKey;
CVMX_MT_3DES_KEY(key[0], 0);
CVMX_MT_3DES_KEY(key[1], 1);
CVMX_MT_3DES_KEY(key[2], 2);
iv = (uint64_t*)des3->reg;
CVMX_MT_3DES_IV(iv[0]);
CVMX_PREFETCH0(inp64);
i0 = *inp64;
/* DES3 assembly can handle 16-byte chunks */
if (inl >= 16) {
CVMX_MT_3DES_DEC_CBC(i0);
inl -= 8;
inp64++;
outp64++;
if (inl >= 8) {
i0 = inp64[0];
CVMX_MF_3DES_RESULT(r0);
CVMX_MT_3DES_DEC_CBC(i0);
for (;;) {
outp64[-1] = r0;
inl -= 8;
inp64++;
outp64++;
i0 = *inp64;
if (inl < 8)
break;
CVMX_PREFETCH(inp64, 64);
CVMX_MF_3DES_RESULT(r0);
CVMX_MT_3DES_DEC_CBC(i0);
}
}
CVMX_MF_3DES_RESULT(r0);
outp64[-1] = r0;
}
/* remainder */
if (inl > 0) {
if (inl <= 8) {
uint64_t r = 0;
XMEMCPY(&r, inp64, inl);
CVMX_MT_3DES_DEC_CBC(r);
CVMX_MF_3DES_RESULT(*outp64);
}
else {
uint64_t r = 0;
i0 = *inp64;
CVMX_MT_3DES_DEC_CBC(i0);
CVMX_MF_3DES_RESULT(*outp64);
inp64++, outp64++;
XMEMCPY(&r, inp64, inl);
CVMX_MT_3DES_DEC_CBC(r);
CVMX_MF_3DES_RESULT(*outp64);
}
}
CVMX_MT_3DES_IV(iv[0]);
return 0;
}
#endif /* !NO_DES3 */
#ifndef NO_AES
#ifdef HAVE_AES_CBC
static int Octeon_AesCbc_Encrypt(Aes *aes,
uint64_t *inp64, uint64_t *outp64, size_t inl)
{
register uint64_t i0, i1, r0, r1;
uint64_t *key, *iv;
if (aes == NULL || inp64 == NULL || outp64 == NULL) {
return BAD_FUNC_ARG;
}
iv = (uint64_t*)aes->reg;
CVMX_MT_AES_IV(iv[0], 0);
CVMX_MT_AES_IV(iv[1], 1);
key = (uint64_t*)aes->devKey;
CVMX_MT_AES_KEY(key[0], 0);
CVMX_MT_AES_KEY(key[1], 1);
CVMX_MT_AES_KEY(key[2], 2);
CVMX_MT_AES_KEY(key[3], 3);
CVMX_MT_AES_KEYLENGTH(aes->keylen/8 - 1);
CVMX_PREFETCH0(inp64);
i0 = inp64[0];
i1 = inp64[1];
/* AES assembly can handle 32-byte chunks */
if (inl >= 32) {
CVMX_MT_AES_ENC_CBC0(i0);
CVMX_MT_AES_ENC_CBC1(i1);
inl -= 16;
inp64 += 2;
outp64 += 2;
if (inl >= 16) {
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
i0 = inp64[0];
i1 = inp64[1];
CVMX_MT_AES_ENC_CBC0(i0);
CVMX_MT_AES_ENC_CBC1(i1);
for (;;) {
outp64[-2] = r0;
outp64[-1] = r1;
outp64 += 2;
inp64 += 2;
inl -= 16;
i0 = inp64[0];
i1 = inp64[1];
if (inl < 16)
break;
CVMX_PREFETCH(inp64, 64);
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
CVMX_MT_AES_ENC_CBC0(i0);
CVMX_MT_AES_ENC_CBC1(i1);
}
}
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
outp64[-2] = r0;
outp64[-1] = r1;
}
/* remainder */
if (inl > 0) {
uint64_t in64[2] = { 0, 0 };
if (inl <= 16) {
XMEMCPY(in64, inp64, inl);
CVMX_MT_AES_ENC_CBC0(in64[0]);
CVMX_MT_AES_ENC_CBC1(in64[1]);
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
outp64[0] = r0;
outp64[1] = r1;
}
else {
CVMX_MT_AES_ENC_CBC0(i0);
CVMX_MT_AES_ENC_CBC1(i1);
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
inl -= 16;
outp64[0] = r0;
outp64[1] = r1;
inp64 += 2;
outp64 += 2;
XMEMCPY(in64, inp64, inl);
CVMX_MT_AES_ENC_CBC0(in64[0]);
CVMX_MT_AES_ENC_CBC1(in64[1]);
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
outp64[0] = r0;
outp64[1] = r1;
}
}
CVMX_MF_AES_IV(iv[0], 0);
CVMX_MF_AES_IV(iv[1], 1);
return 0;
}
static int Octeon_AesCbc_Decrypt(Aes *aes,
uint64_t *inp64, uint64_t *outp64, size_t inl)
{
register uint64_t i0, i1, r0, r1;
uint64_t *key, *iv;
if (aes == NULL || inp64 == NULL || outp64 == NULL) {
return BAD_FUNC_ARG;
}
iv = (uint64_t*)aes->reg;
key = (uint64_t*)aes->devKey;
CVMX_MT_AES_IV(iv[0], 0);
CVMX_MT_AES_IV(iv[1], 1);
CVMX_MT_AES_KEY(key[0], 0);
CVMX_MT_AES_KEY(key[1], 1);
CVMX_MT_AES_KEY(key[2], 2);
CVMX_MT_AES_KEY(key[3], 3);
CVMX_MT_AES_KEYLENGTH(aes->keylen/8 - 1);
CVMX_PREFETCH0(inp64);
i0 = inp64[0];
i1 = inp64[1];
/* AES assembly can handle 32-byte chunks */
if (inl >= 32) {
CVMX_MT_AES_DEC_CBC0(i0);
CVMX_MT_AES_DEC_CBC1(i1);
inp64 += 2;
outp64 += 2;
inl -= 16;
if (inl >= 16) {
i0 = inp64[0];
i1 = inp64[1];
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
CVMX_MT_AES_DEC_CBC0(i0);
CVMX_MT_AES_DEC_CBC1(i1);
for (;;) {
outp64[-2] = r0;
outp64[-1] = r1;
outp64 += 2;
inp64 += 2;
inl -= 16;
i0 = inp64[0];
i1 = inp64[1];
if (inl < 16)
break;
CVMX_PREFETCH(inp64, 64);
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
CVMX_MT_AES_DEC_CBC0(i0);
CVMX_MT_AES_DEC_CBC1(i1);
}
}
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
outp64[-2] = r0;
outp64[-1] = r1;
}
/* remainder */
if (inl > 0) {
uint64_t in64[2] = { 0, 0 };
XMEMCPY(in64, inp64, inl);
CVMX_MT_AES_DEC_CBC0(in64[0]);
CVMX_MT_AES_DEC_CBC1(in64[1]);
CVMX_MF_AES_RESULT(r0, 0);
CVMX_MF_AES_RESULT(r1, 1);
outp64[0] = r0;
outp64[1] = r1;
}
CVMX_MF_AES_IV(iv[0], 0);
CVMX_MF_AES_IV(iv[1], 1);
return 0;
}
#endif /* HAVE_AES_CBC */
#ifdef HAVE_AESGCM
#define CVM_AES_RD_RESULT_WR_DATA(in1, in2, out1, out2) \
asm volatile(\
".set noreorder \n" \
"dmfc2 %[r1],0x0100\n" \
"dmfc2 %[r2],0x0101\n" \
"dmtc2 %[r3],0x010a\n" \
"dmtc2 %[r4],0x310b\n" \
".set reorder \n" \
: [r1] "=&d"(in1) , [r2] "=&d"(in2) \
: [r3] "d"(out1), [r4] "d"(out2))
static NOOPT void Octeon_GHASH_Restore(word16 poly, byte* h)
{
word64* bigH = (word64*)h;
CVMX_MT_GFM_POLY((word64)poly);
CVMX_MT_GFM_MUL(bigH[0], 0);
CVMX_MT_GFM_MUL(bigH[1], 1);
}
static NOOPT void Octeon_GHASH_Init(word16 poly, byte* h)
{
Octeon_GHASH_Restore(poly, h);
CVMX_MT_GFM_RESINP(0, 0);
CVMX_MT_GFM_RESINP(0, 1);
}
static NOOPT void Octeon_GHASH_Update(byte* in)
{
word64* bigIn = (word64*)in;
CVMX_MT_GFM_XOR0(bigIn[0]);
CVMX_MT_GFM_XORMUL1(bigIn[1]);
}
static NOOPT void Octeon_GHASH_Final(byte* out, word64 authInSz, word64 inSz)
{
word64* bigOut = (word64*)out;
CVMX_MT_GFM_XOR0(authInSz * 8);
CVMX_MT_GFM_XORMUL1(inSz * 8);
CVMX_MF_GFM_RESINP(bigOut[0], 0);
CVMX_MF_GFM_RESINP(bigOut[1], 1);
}
/* Sets the Octeon key with the key found in the Aes record. */
static NOOPT int Octeon_AesGcm_SetKey(Aes* aes)
{
int ret = 0;
if (aes == NULL)
ret = BAD_FUNC_ARG;
if (ret == 0) {
uint64_t* key = (uint64_t*)aes->devKey;
CVMX_MT_AES_KEY(key[0], 0);
CVMX_MT_AES_KEY(key[1], 1);
CVMX_MT_AES_KEY(key[2], 2);
CVMX_MT_AES_KEY(key[3], 3);
CVMX_MT_AES_KEYLENGTH((aes->keylen / 8) - 1);
if (!aes->keySet) {
uint64_t* bigH = (uint64_t*)aes->H;
CVMX_MT_AES_ENC0(0);
CVMX_MT_AES_ENC1(0);
CVMX_MF_AES_RESULT(bigH[0], 0);
CVMX_MF_AES_RESULT(bigH[1], 1);
aes->keySet = 1;
}
}
return ret;
}
static NOOPT int Octeon_AesGcm_SetIV(Aes* aes, byte* iv, word32 ivSz)
{
int ret = 0;
if (aes == NULL || iv == NULL)
ret = BAD_FUNC_ARG;
if (ret == 0) {
if (ivSz == GCM_NONCE_MID_SZ) {
XMEMSET((byte*)aes->reg, 0, sizeof(aes->reg));
XMEMCPY((byte*)aes->reg, iv, ivSz);
aes->reg[3] = 1;
}
else {
int blocks, remainder, i;
byte aesBlock[AES_BLOCK_SIZE];
blocks = ivSz / AES_BLOCK_SIZE;
remainder = ivSz % AES_BLOCK_SIZE;
for (i = 0; i < blocks; i++, iv += AES_BLOCK_SIZE)
Octeon_GHASH_Update(iv);
XMEMSET(aesBlock, 0, sizeof(aesBlock));
for (i = 0; i < remainder; i++)
aesBlock[i] = iv[i];
Octeon_GHASH_Update(aesBlock);
Octeon_GHASH_Final((byte*)aes->reg, 0, ivSz);
}
aes->y0 = aes->reg[3];
aes->reg[3]++;
Octeon_GHASH_Init(0xe100, aes->H);
}
return ret;
}
static NOOPT int Octeon_AesGcm_SetAAD(Aes* aes, byte* aad, word32 aadSz)
{
word64* p;
ALIGN16 byte aesBlock[AES_BLOCK_SIZE];
int blocks, remainder, i;
if (aes == NULL || (aadSz != 0 && aad == NULL))
return BAD_FUNC_ARG;
if (aadSz == 0)
return 0;
blocks = aadSz / AES_BLOCK_SIZE;
remainder = aadSz % AES_BLOCK_SIZE;
Octeon_GHASH_Restore(0xe100, aes->H);
p = (word64*)aesBlock;
for (i = 0; i < blocks; i++, aad += AES_BLOCK_SIZE) {
CVMX_LOADUNA_INT64(p[0], aad, 0);
CVMX_LOADUNA_INT64(p[1], aad, 8);
CVMX_MT_GFM_XOR0(p[0]);
CVMX_MT_GFM_XORMUL1(p[1]);
}
XMEMSET(aesBlock, 0, sizeof(aesBlock));
for (i = 0; i < remainder; i++)
aesBlock[i] = aad[i];
CVMX_MT_GFM_XOR0(p[0]);
CVMX_MT_GFM_XORMUL1(p[1]);
return 0;
}
static int Octeon_AesGcm_SetEncrypt(Aes* aes, byte* in, byte* out, word32 inSz,
int encrypt)
{
word32 i, blocks, remainder;
ALIGN16 byte aesBlockIn[AES_BLOCK_SIZE];
ALIGN16 byte aesBlockOut[AES_BLOCK_SIZE];
word64* pIn;
word64* pOut;
word64* pIv;
if (aes == NULL || in == NULL || out == NULL)
return BAD_FUNC_ARG;
pIn = (word64*)aesBlockIn;
pOut = (word64*)aesBlockOut;
pIv = (word64*)aes->reg;
CVMX_PREFETCH0(in);
CVMX_MT_AES_ENC0(pIv[0]);
CVMX_MT_AES_ENC1(pIv[1]);
blocks = inSz / AES_BLOCK_SIZE;
remainder = inSz % AES_BLOCK_SIZE;
for (i = 0; i < blocks;
i++, in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE) {
CVMX_PREFETCH128(in);
aes->reg[3]++;
CVMX_LOADUNA_INT64(pIn[0], in, 0);
CVMX_LOADUNA_INT64(pIn[1], in, 8);
CVM_AES_RD_RESULT_WR_DATA(pOut[0], pOut[1], pIv[0], pIv[1]);
if (encrypt) {
pOut[0] ^= pIn[0];
pOut[1] ^= pIn[1];
CVMX_MT_GFM_XOR0(pOut[0]);
CVMX_MT_GFM_XORMUL1(pOut[1]);
}
else {
CVMX_MT_GFM_XOR0(pIn[0]);
CVMX_MT_GFM_XORMUL1(pIn[1]);
pOut[0] ^= pIn[0];
pOut[1] ^= pIn[1];
}
CVMX_STOREUNA_INT64(pOut[0], out, 0);
CVMX_STOREUNA_INT64(pOut[1], out, 8);
}
if (remainder > 0) {
ALIGN16 byte aesBlockMask[AES_BLOCK_SIZE];
word64* pMask = (word64*)aesBlockMask;
XMEMSET(aesBlockOut, 0, sizeof(aesBlockOut));
XMEMSET(aesBlockMask, 0, sizeof(aesBlockMask));
for (i = 0; i < remainder; i++) {
aesBlockIn[i] = in[i];
aesBlockMask[i] = 0xFF;
}
if (encrypt) {
CVMX_MF_AES_RESULT(pOut[0], 0);
CVMX_MF_AES_RESULT(pOut[1], 1);
pOut[0] ^= pIn[0];
pOut[1] ^= pIn[1];
pOut[0] &= pMask[0];
pOut[1] &= pMask[1];
CVMX_MT_GFM_XOR0(pOut[0]);
CVMX_MT_GFM_XORMUL1(pOut[1]);
}
else {
CVMX_MT_GFM_XOR0(pIn[0]);
CVMX_MT_GFM_XORMUL1(pIn[1]);
CVMX_MF_AES_RESULT(pOut[0], 0);
CVMX_MF_AES_RESULT(pOut[1], 1);
pOut[0] ^= pIn[0];
pOut[1] ^= pIn[1];
pOut[0] &= pMask[0];
pOut[1] &= pMask[1];
}
for (i = 0; i < remainder; i++)
out[i] = aesBlockOut[i];
}
return 0;
}
static NOOPT int Octeon_AesGcm_Finalize(Aes* aes, word32 inSz, word32 aadSz,
byte* tag)
{
word64 bigSz;
word64* pIv;
word64* pIn;
word64* pOut;
uint32_t countSave;
ALIGN16 byte aesBlockIn[AES_BLOCK_SIZE];
ALIGN16 byte aesBlockOut[AES_BLOCK_SIZE];
countSave = aes->reg[3];
aes->reg[3] = aes->y0;
pIv = (word64*)aes->reg;
CVMX_MT_AES_ENC0(pIv[0]);
CVMX_MT_AES_ENC1(pIv[1]);
bigSz = (word64)aadSz * 8;
CVMX_MT_GFM_XOR0(bigSz);
bigSz = (word64)inSz * 8;
CVMX_MT_GFM_XORMUL1(bigSz);
aes->reg[3] = countSave;
pIn = (word64*)aesBlockIn;
CVMX_MF_AES_RESULT(pIn[0], 0);
CVMX_MF_AES_RESULT(pIn[1], 1);
pOut = (word64*)aesBlockOut;
CVMX_MF_GFM_RESINP(pOut[0], 0);
CVMX_MF_GFM_RESINP(pOut[1], 1);
pOut[0] ^= pIn[0];
pOut[1] ^= pIn[1];
CVMX_STOREUNA_INT64(pOut[0], tag, 0);
CVMX_STOREUNA_INT64(pOut[1], tag, 8);
return 0;
}
static int Octeon_AesGcm_Encrypt(Aes* aes, byte* in, byte* out, word32 inSz,
byte* iv, word32 ivSz, byte* aad, word32 aadSz, byte* tag)
{
int ret = 0;
if (aes == NULL)
ret = BAD_FUNC_ARG;
if (ret == 0)
ret = Octeon_AesGcm_SetKey(aes);
if (ret == 0)
ret = Octeon_AesGcm_SetIV(aes, iv, ivSz);
if (ret == 0)
ret = Octeon_AesGcm_SetAAD(aes, aad, aadSz);
if (ret == 0)
ret = Octeon_AesGcm_SetEncrypt(aes, in, out, inSz, 1);
if (ret == 0)
ret = Octeon_AesGcm_Finalize(aes, inSz, aadSz, tag);
return ret;
}
static int Octeon_AesGcm_Decrypt(Aes* aes, byte* in, byte* out, word32 inSz,
byte* iv, word32 ivSz, byte* aad, word32 aadSz, byte* tag)
{
int ret = 0;
if (aes == NULL)
ret = BAD_FUNC_ARG;
if (ret == 0)
ret = Octeon_AesGcm_SetKey(aes);
if (ret == 0)
ret = Octeon_AesGcm_SetIV(aes, iv, ivSz);
if (ret == 0)
ret = Octeon_AesGcm_SetAAD(aes, aad, aadSz);
if (ret == 0)
ret = Octeon_AesGcm_SetEncrypt(aes, in, out, inSz, 0);
if (ret == 0)
ret = Octeon_AesGcm_Finalize(aes, inSz, aadSz, tag);
return ret;
}
#endif /* HAVE_AESGCM */
#endif /* !NO_AES */
#ifdef WOLF_CRYPTO_CB
#include <wolfssl/wolfcrypt/cryptocb.h>
static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
{
int ret = NOT_COMPILED_IN; /* return this to bypass HW and use SW */
if (info == NULL)
return BAD_FUNC_ARG;
#ifdef DEBUG_WOLFSSL
printf("CryptoDevCb: Algo Type %d\n", info->algo_type);
#endif
if (info->algo_type == WC_ALGO_TYPE_CIPHER) {
#if !defined(NO_AES) || !defined(NO_DES3)
#ifdef HAVE_AESGCM
if (info->cipher.type == WC_CIPHER_AES_GCM) {
if (info->cipher.enc) {
ret = Octeon_AesGcm_Encrypt(
info->cipher.aesgcm_enc.aes,
(byte*)info->cipher.aesgcm_enc.in,
(byte*)info->cipher.aesgcm_enc.out,
info->cipher.aesgcm_enc.sz,
(byte*)info->cipher.aesgcm_enc.iv,
info->cipher.aesgcm_enc.ivSz,
(byte*)info->cipher.aesgcm_enc.authIn,
info->cipher.aesgcm_enc.authInSz,
(byte*)info->cipher.aesgcm_enc.authTag);
}
else {
ret = Octeon_AesGcm_Decrypt(
info->cipher.aesgcm_dec.aes,
(byte*)info->cipher.aesgcm_dec.in,
(byte*)info->cipher.aesgcm_dec.out,
info->cipher.aesgcm_dec.sz,
(byte*)info->cipher.aesgcm_dec.iv,
info->cipher.aesgcm_dec.ivSz,
(byte*)info->cipher.aesgcm_dec.authIn,
info->cipher.aesgcm_dec.authInSz,
(byte*)info->cipher.aesgcm_dec.authTag);
}
}
#endif /* HAVE_AESGCM */
#ifdef HAVE_AES_CBC
if (info->cipher.type == WC_CIPHER_AES_CBC) {
if (info->cipher.enc) {
ret = Octeon_AesCbc_Encrypt(
info->cipher.aescbc.aes,
(word64*)info->cipher.aescbc.in,
(word64*)info->cipher.aescbc.out,
info->cipher.aescbc.sz);
}
else {
ret = Octeon_AesCbc_Decrypt(
info->cipher.aescbc.aes,
(word64*)info->cipher.aescbc.in,
(word64*)info->cipher.aescbc.out,
info->cipher.aescbc.sz);
}
}
#endif /* HAVE_AES_CBC */
#ifndef NO_DES3
if (info->cipher.type == WC_CIPHER_DES3) {
if (info->cipher.enc) {
ret = Octeon_Des3_CbcEncrypt(
info->cipher.des3.des,
(word64*)info->cipher.des3.in,
(word64*)info->cipher.des3.out,
info->cipher.des3.sz);
}
else {
ret = Octeon_Des3_CbcDecrypt(
info->cipher.des3.des,
(word64*)info->cipher.des3.in,
(word64*)info->cipher.des3.out,
info->cipher.des3.sz);
}
}
#endif /* !NO_DES3 */
#endif /* !NO_AES || !NO_DES3 */
}
(void)devIdArg;
(void)ctx;
return ret;
}
int wc_CryptoCb_InitOcteon(void)
{
if (wc_CryptoCb_RegisterDevice(devId, myCryptoDevCb, NULL) < 0) {
return INVALID_DEVID;
}
return devId;
}
void wc_CryptoCb_CleanupOcteon(int* id)
{
wc_CryptoCb_UnRegisterDevice(*id);
*id = INVALID_DEVID;
}
#endif /* WOLF_CRYPTO_CB */
#endif /* HAVE_CAVIUM_OCTEON_SYNC */

View file

@ -1,43 +0,0 @@
# Description
Used to build with cryptodev-linux library with Linux OS.
# Quick Start
## Installing cryptodev module
If not already installed then the cryptodev-linux module will need installed.
```
git clone https://github.com/cryptodev-linux/cryptodev-linux.git
cd cryptodev-linux
make
sudo make install
modprobe cryptodev
```
## Options for building wolfSSL
For default build with all supported features use:
```
./configure --enable-cryptodev
```
Or for more control over features used:
```
./configure --enable-devcrypto=cbc
./configure --enable-devcrypto=hash
./configure --enable-devcrypto=aes
./configure --enable-devcrypto=all
```
Then build the wolfSSL library with:
```
make
sudo make install
./wolfcrypt/test/testwolfcrypt
```

View file

@ -1,384 +0,0 @@
/* devcrypto_aes.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#if !defined(NO_AES) && defined(WOLFSSL_DEVCRYPTO)
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#if defined(HAVE_AES_CBC) && defined(WOLFSSL_DEVCRYPTO_CBC)
int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct crypt_op crt;
int ret;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
/* encrypt only up to AES block size of date */
sz = sz - (sz % AES_BLOCK_SIZE);
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CBC,
(byte*)aes->devKey, aes->keylen);
if (ret != 0)
return ret;
}
wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg,
COP_ENCRYPT);
ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt);
if (ret != 0) {
return WC_DEVCRYPTO_E;
}
/* store iv for next call */
XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
return 0;
}
#ifdef HAVE_AES_DECRYPT
int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
struct crypt_op crt;
int ret;
if (aes == NULL || out == NULL || in == NULL || sz % AES_BLOCK_SIZE != 0) {
return BAD_FUNC_ARG;
}
XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CBC,
(byte*)aes->devKey, aes->keylen);
if (ret != 0)
return ret;
}
wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg,
COP_DECRYPT);
ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt);
if (ret != 0) {
return WC_DEVCRYPTO_E;
}
XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE);
return 0;
}
#endif /* HAVE_AES_DECRYPT */
#endif /* HAVE_AES_CBC && WOLFSSL_DEVCRYPTO_CBC */
#ifdef WOLFSSL_DEVCRYPTO_AES /* all AES algorithms supported */
int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen,
const byte* iv, int dir)
{
#if defined(AES_MAX_KEY_SIZE)
const word32 max_key_len = (AES_MAX_KEY_SIZE / 8);
#endif
if (aes == NULL ||
!((keylen == 16) || (keylen == 24) || (keylen == 32))) {
return BAD_FUNC_ARG;
}
#if defined(AES_MAX_KEY_SIZE)
/* Check key length */
if (keylen > max_key_len) {
return BAD_FUNC_ARG;
}
#endif
aes->keylen = keylen;
aes->rounds = keylen/4 + 6;
#ifdef WOLFSSL_AES_COUNTER
aes->left = 0;
#endif
aes->ctx.cfd = -1;
XMEMCPY(aes->devKey, userKey, keylen);
(void)dir;
return wc_AesSetIV(aes, iv);
}
/* AES-DIRECT */
#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AES_ECB)
/* common code between ECB encrypt and decrypt
* returns 0 on success */
static int wc_DevCrypto_AesDirect(Aes* aes, byte* out, const byte* in,
word32 sz, int dir)
{
int ret;
struct crypt_op crt;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_ECB, (byte*)aes->devKey,
aes->keylen);
if (ret != 0)
return ret;
}
wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, NULL, dir);
ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt);
if (ret != 0) {
return WC_DEVCRYPTO_E;
}
return 0;
}
#endif
#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM)
void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in)
{
wc_DevCrypto_AesDirect(aes, out, in, AES_BLOCK_SIZE, COP_ENCRYPT);
}
void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in)
{
wc_DevCrypto_AesDirect(aes, out, in, AES_BLOCK_SIZE, COP_DECRYPT);
}
int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen,
const byte* iv, int dir)
{
return wc_AesSetKey(aes, userKey, keylen, iv, dir);
}
#endif
/* AES-CTR */
#if defined(WOLFSSL_AES_COUNTER)
/* Increment AES counter */
static WC_INLINE void IncrementAesCounter(byte* inOutCtr)
{
/* in network byte order so start at end and work back */
int i;
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
if (++inOutCtr[i]) /* we're done unless we overflow */
return;
}
}
int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
int ret;
struct crypt_op crt;
byte* tmp;
if (aes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
/* consume any unused bytes left in aes->tmp */
tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left;
while (aes->left && sz) {
*(out++) = *(in++) ^ *(tmp++);
aes->left--;
sz--;
}
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_CTR, (byte*)aes->devKey,
aes->keylen);
if (ret != 0)
return ret;
}
if (sz > 0) {
/* clear previously leftover data */
tmp = (byte*)aes->tmp;
XMEMSET(tmp, 0, AES_BLOCK_SIZE);
/* update IV */
wc_SetupCryptSym(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)aes->reg,
COP_ENCRYPT);
ret = ioctl(aes->ctx.cfd, CIOCCRYPT, &crt);
if (ret != 0) {
return WC_DEVCRYPTO_E;
}
/* adjust counter after call to hardware */
while (sz >= AES_BLOCK_SIZE) {
IncrementAesCounter((byte*)aes->reg);
sz -= AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
}
}
/* create key stream for later if needed */
if (sz > 0) {
Aes tmpAes;
wc_AesSetKey(&tmpAes, (byte*)aes->devKey, aes->keylen, (byte*)aes->reg,
AES_ENCRYPTION);
wc_AesEncryptDirect(&tmpAes, (byte*)aes->tmp, (const byte*)aes->reg);
wc_AesFree(&tmpAes);
IncrementAesCounter((byte*)aes->reg);
aes->left = AES_BLOCK_SIZE - (sz % AES_BLOCK_SIZE);
}
return 0;
}
#endif /* WOLFSSL_AES_COUNTER */
#ifdef HAVE_AESGCM
int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
{
return wc_AesSetKey(aes, key, len, NULL, AES_ENCRYPTION);
}
/* common code for AES-GCM encrypt/decrypt */
static int wc_DevCrypto_AesGcm(Aes* aes, byte* out, byte* in, word32 sz,
const byte* iv, word32 ivSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz,
int dir)
{
struct crypt_auth_op crt = {0};
int ret;
byte scratch[AES_BLOCK_SIZE];
/* argument checks */
if (aes == NULL || authTagSz > AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
/* Account for NULL in/out buffers. Up to tag size is still written into
* in/out buffers */
if (out == NULL)
out = scratch;
if (in == NULL)
in = scratch;
XMEMSET(scratch, 0, AES_BLOCK_SIZE);
if (aes->ctx.cfd == -1) {
ret = wc_DevCryptoCreate(&aes->ctx, CRYPTO_AES_GCM, (byte*)aes->devKey,
aes->keylen);
if (ret != 0)
return ret;
}
/* if decrypting then the tag is expected to be at the end of "in" buffer */
if (dir == COP_DECRYPT) {
XMEMCPY(in + sz, authTag, authTagSz);
sz += authTagSz;
}
else{
/* get full tag from hardware */
authTagSz = AES_BLOCK_SIZE;
}
wc_SetupCryptAead(&crt, &aes->ctx, (byte*)in, sz, out, (byte*)iv, ivSz,
dir, (byte*)authIn, authInSz, authTag, authTagSz);
ret = ioctl(aes->ctx.cfd, CIOCAUTHCRYPT, &crt);
if (ret != 0) {
if (dir == COP_DECRYPT) {
return AES_GCM_AUTH_E;
}
else {
return WC_DEVCRYPTO_E;
}
}
/* after encryption the tag has been placed at the end of "out" buffer */
if (dir == COP_ENCRYPT) {
XMEMCPY(authTag, out + sz, authTagSz);
}
return 0;
}
/* it is assumed that "out" buffer has enough room for cipher text + tag */
int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* iv, word32 ivSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
WOLFSSL_MSG("GcmEncrypt authTagSz too small error");
return BAD_FUNC_ARG;
}
return wc_DevCrypto_AesGcm(aes, out, (byte*)in, sz, iv, ivSz,
authTag, authTagSz, authIn, authInSz,
COP_ENCRYPT);
}
#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT)
/* it is assumed that "in" buffer has enough room for cipher text + tag */
int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
const byte* iv, word32 ivSz,
const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
return wc_DevCrypto_AesGcm(aes, out, (byte*)in, sz, iv, ivSz,
(byte*)authTag, authTagSz, authIn, authInSz,
COP_DECRYPT);
}
#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */
#endif /* HAVE_AESGCM */
#ifdef HAVE_AES_ECB
int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_DevCrypto_AesDirect(aes, out, in, sz, COP_ENCRYPT);
}
int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
return wc_DevCrypto_AesDirect(aes, out, in, sz, COP_DECRYPT);
}
#endif /* HAVE_AES_ECB */
#endif /* WOLFSSL_DEVCRYPTO_AES */
#endif /* !NO_AES && WOLFSSL_DEVCRYPTO */

View file

@ -1,248 +0,0 @@
/* devcrypto_hash.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_DEVCRYPTO_HASH)
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
#if !defined(NO_SHA256)
#include <wolfssl/wolfcrypt/sha256.h>
#endif
/* dereference structure based on type to get cryptodev context pointer
* can return NULL on fail case */
static WC_CRYPTODEV* GetHashContext(void* ctx, int type)
{
switch (type) {
case CRYPTO_SHA2_256:
return &((wc_Sha256*)ctx)->ctx;
default:
return NULL;
}
return NULL;
}
/* generic hash initialization
* key is for hmac algorithms and keySz is for the size of key buffer
* key should be null in the case of non hmac algorithms
* return 0 on success */
static int HashInit(void* ctx, int type, byte* key, word32 keySz)
{
WC_CRYPTODEV* cdev;
if ((cdev = GetHashContext(ctx, type)) == NULL) {
WOLFSSL_MSG("Unsupported hash type");
return BAD_FUNC_ARG;
}
return wc_DevCryptoCreate(cdev, type, key, keySz);
}
/* generic function for updated hash structure
* returns 0 on success */
static int HashUpdate(void* ctx, int type, const byte* input, word32 inputSz)
{
WC_CRYPTODEV* dev;
struct crypt_op crt;
byte digest[64];
if (inputSz == 0) {
return 0;
}
if ((dev = GetHashContext(ctx, type)) == NULL) {
WOLFSSL_MSG("Unsupported hash type");
return BAD_FUNC_ARG;
}
wc_SetupCrypt(&crt, dev, (byte*)input, inputSz, NULL, digest, COP_FLAG_UPDATE);
if (ioctl(dev->cfd, CIOCCRYPT, &crt)) {
WOLFSSL_MSG("Error with call to ioctl");
return WC_DEVCRYPTO_E;
}
return 0;
}
/* generic function for getting final digest value */
static int GetDigest(void* ctx, int type, byte* out)
{
WC_CRYPTODEV* dev;
struct crypt_op crt;
if ((dev = GetHashContext(ctx, type)) == NULL) {
WOLFSSL_MSG("Unsupported hash type");
return BAD_FUNC_ARG;
}
wc_SetupCrypt(&crt, dev, NULL, 0, NULL, out, COP_FLAG_FINAL);
if (ioctl(dev->cfd, CIOCCRYPT, &crt)) {
WOLFSSL_MSG("Error with call to ioctl");
return WC_DEVCRYPTO_E;
}
return 0;
}
#if !defined(NO_SHA256)
int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
{
if (sha == NULL) {
return BAD_FUNC_ARG;
}
(void)devId; /* no async for now */
XMEMSET(sha, 0, sizeof(wc_Sha256));
sha->heap = heap;
return HashInit((void*)sha, CRYPTO_SHA2_256, NULL, 0);
}
int wc_Sha256Update(wc_Sha256* sha, const byte* in, word32 sz)
{
if (sha == NULL || (sz > 0 && in == NULL)) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP
/* keep full message to hash at end instead of incremental updates */
if (sha->len < sha->used + sz) {
if (sha->msg == NULL) {
sha->msg = (byte*)XMALLOC(sha->used + sz, sha->heap,
DYNAMIC_TYPE_TMP_BUFFER);
} else {
byte* pt = (byte*)XREALLOC(sha->msg, sha->used + sz, sha->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (pt == NULL) {
return MEMORY_E;
}
sha->msg = pt;
}
if (sha->msg == NULL) {
return MEMORY_E;
}
sha->len = sha->used + sz;
}
XMEMCPY(sha->msg + sha->used, in, sz);
sha->used += sz;
return 0;
#else
return HashUpdate(sha, CRYPTO_SHA2_256, in, sz);
#endif
}
int wc_Sha256Final(wc_Sha256* sha, byte* hash)
{
int ret;
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
/* help static analysis tools out */
XMEMSET(hash, 0, WC_SHA256_DIGEST_SIZE);
#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP
/* keep full message to hash at end instead of incremental updates */
if ((ret = HashUpdate(sha, CRYPTO_SHA2_256, sha->msg, sha->used)) < 0) {
return ret;
}
XFREE(sha->msg, sha->heap, DYNAMIC_TYPE_TMP_BUFFER);
sha->msg = NULL;
#endif
ret = GetDigest(sha, CRYPTO_SHA2_256, hash);
if (ret != 0) {
return ret;
}
wc_Sha256Free(sha);
return wc_InitSha256_ex(sha, sha->heap, 0);
}
int wc_Sha256GetHash(wc_Sha256* sha, byte* hash)
{
if (sha == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP
{
int ret;
wc_Sha256 cpy;
wc_Sha256Copy(sha, &cpy);
if ((ret = HashUpdate(&cpy, CRYPTO_SHA2_256, cpy.msg, cpy.used)) == 0) {
/* help static analysis tools out */
XMEMSET(hash, 0, WC_SHA256_DIGEST_SIZE);
ret = GetDigest(&cpy, CRYPTO_SHA2_256, hash);
}
wc_Sha256Free(&cpy);
return ret;
}
#else
(void)sha;
(void)hash;
WOLFSSL_MSG("Compile with WOLFSSL_DEVCRYPTO_HASH_KEEP for this feature");
return NOT_COMPILED_IN;
#endif
}
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
{
if (src == NULL || dst == NULL) {
return BAD_FUNC_ARG;
}
wc_InitSha256_ex(dst, src->heap, 0);
#ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP
dst->len = src->len;
dst->used = src->used;
dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (dst->msg == NULL) {
return MEMORY_E;
}
XMEMCPY(dst->msg, src->msg, src->len);
#endif
return 0;
}
#endif /* !NO_SHA256 */
#endif /* WOLFSSL_DEVCRYPTO */

View file

@ -1,167 +0,0 @@
/* wc_devcrypto.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_DEVCRYPTO)
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
/* sets up a context for talking to /dev/crypto
* return 0 on success */
int wc_DevCryptoCreate(WC_CRYPTODEV* ctx, int type, byte* key, word32 keySz)
{
int fd;
int isHash = 0; /* flag for if hashing algorithm */
if (ctx == NULL) {
return BAD_FUNC_ARG;
}
/* sanity check on session type before creating descriptor */
XMEMSET(ctx, 0, sizeof(WC_CRYPTODEV));
switch (type) {
case CRYPTO_SHA1:
case CRYPTO_SHA2_256:
isHash = 1;
break;
#ifndef NO_AES
case CRYPTO_AES_CTR:
case CRYPTO_AES_ECB:
case CRYPTO_AES_GCM:
case CRYPTO_AES_CBC:
isHash = 0;
break;
#endif
default:
WOLFSSL_MSG("Unknown / Unimplemented algorithm type");
return BAD_FUNC_ARG;
}
/* create descriptor */
if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
WOLFSSL_MSG("Error opening /dev/crypto is cryptodev module loaded?");
return WC_DEVCRYPTO_E;
}
if (fcntl(fd, F_SETFD, 1) == -1) {
WOLFSSL_MSG("Error setting F_SETFD with fcntl");
close(fd);
return WC_DEVCRYPTO_E;
}
/* set up session */
ctx->cfd = fd;
if (isHash) {
ctx->sess.mac = type;
}
else {
ctx->sess.cipher = type;
ctx->sess.key = (void*)key;
ctx->sess.keylen = keySz;
}
if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
close(fd);
WOLFSSL_MSG("Error starting cryptodev session");
return WC_DEVCRYPTO_E;
}
(void)key;
(void)keySz;
return 0;
}
/* free up descriptor and session used with ctx */
void wc_DevCryptoFree(WC_CRYPTODEV* ctx)
{
if (ctx != NULL && ctx->cfd >= 0) {
if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
WOLFSSL_MSG("Error stopping cryptodev session");
}
close(ctx->cfd);
}
}
/* setup crypt_op structure */
void wc_SetupCrypt(struct crypt_op* crt, WC_CRYPTODEV* dev,
byte* src, int srcSz, byte* dst, byte* dig, int flag)
{
XMEMSET(crt, 0, sizeof(struct crypt_op));
crt->ses = dev->sess.ses;
crt->src = src;
crt->len = srcSz;
crt->dst = dst;
crt->mac = dig;
crt->flags = flag;
}
/* setup crypt_op structure for symmetric key operations */
void wc_SetupCryptSym(struct crypt_op* crt, WC_CRYPTODEV* dev,
byte* src, word32 srcSz, byte* dst, byte* iv, int flag)
{
XMEMSET(crt, 0, sizeof(struct crypt_op));
crt->ses = dev->sess.ses;
crt->src = src;
crt->len = srcSz;
crt->dst = dst;
crt->iv = iv;
crt->op = flag;
}
/* setup crypt_auth_op structure for aead operations */
void wc_SetupCryptAead(struct crypt_auth_op* crt, WC_CRYPTODEV* dev,
byte* src, word32 srcSz, byte* dst, byte* iv, word32 ivSz, int flag,
byte* authIn, word32 authInSz, byte* authTag, word32 authTagSz)
{
XMEMSET(crt, 0, sizeof(struct crypt_op));
crt->ses = dev->sess.ses;
crt->src = src;
crt->len = srcSz;
crt->dst = dst;
crt->iv = iv;
crt->iv_len = ivSz;
crt->op = flag;
/* also set auth in and tag */
crt->auth_src = authIn;
crt->auth_len = authInSz;
crt->tag = authTag;
crt->tag_len = authTagSz;
}
#endif /* WOLFSSL_DEVCRYPTO */

View file

@ -1,3 +0,0 @@
# Intel QuickAssist Adapter Asynchronous Support
Please contact wolfSSL at info@wolfssl.com to request an evaluation.

View file

@ -1,146 +0,0 @@
/* mynewt_port.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#if defined(WOLFSSL_APACHE_MYNEWT)
#ifndef NO_FILESYSTEM
#include "fs/fs.h"
#define FILE struct fs_file
FILE* mynewt_fopen(const char * restrict path, const char * restrict mode)
{
FILE *file;
uint8_t access_flags = 0;
const char *p = mode;
while(*p != '\0') {
switch(*p) {
case 'r':
{
access_flags |= FS_ACCESS_READ;
if(*(p+1) == '+') {
access_flags |= FS_ACCESS_WRITE;
}
}
break;
case 'w':
{
access_flags |= (FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE);
if(*(p+1) == '+') {
access_flags |= FS_ACCESS_READ;
}
}
break;
case 'a':
{
access_flags |= (FS_ACCESS_WRITE | FS_ACCESS_APPEND);
if(*(p+1) == '+') {
access_flags |= FS_ACCESS_READ;
}
}
break;
}
p++;
}
/* Open the file for reading. */
int rc = fs_open(path, access_flags, &file);
if (rc != 0) {
return NULL;
}
return file;
}
int mynewt_fseek(FILE *stream, long offset, int whence)
{
uint32_t fs_offset;
switch(whence) {
case 0: /* SEEK_SET */
{
fs_offset += offset;
}
break;
case 1: /* SEEK_CUR */
{
fs_offset = fs_getpos(stream);
fs_offset += offset;
}
break;
case 2: /* SEEK_END */
{
fs_filelen(stream, &fs_offset);
fs_offset += offset;
}
break;
}
fs_seek(stream, fs_offset);
return 0;
}
long mynewt_ftell(FILE *stream)
{
uint32_t fs_offset;
fs_filelen(stream, &fs_offset);
fs_seek(stream, fs_offset);
return (long)fs_offset;
}
void mynewt_rewind(FILE *stream)
{
fs_seek(stream, 0);
}
size_t mynewt_fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
size_t to_read = size * nitems;
uint32_t read_size;
int rc = fs_read(stream, to_read, ptr, &read_size);
if(rc != 0) {
return 0;
}
return (size_t)read_size;
}
size_t mynewt_fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
size_t to_write = size * nitems;
int rc = fs_write(stream, ptr, to_write);
if(rc != 0) {
return 0;
}
return to_write;
}
int mynewt_fclose(FILE *stream)
{
fs_close(stream);
return 0;
}
#endif /* NO_FILESYSTEM*/
#endif /* if defined(WOLFSSL_APACHE_MYNEWT) */

View file

@ -1,220 +0,0 @@
/* nrf51.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef WOLFSSL_NRF51
#include "bsp.h"
#include "nrf_delay.h"
#include "app_uart.h"
#include "app_error.h"
#include "nrf_drv_rng.h"
#include "nrf_drv_rtc.h"
#include "nrf_drv_clock.h"
#include "nrf_ecb.h"
#ifdef SOFTDEVICE_PRESENT
#include "softdevice_handler.h"
#include "nrf_soc.h"
#endif /* SOFTDEVICE_PRESENT */
/* RTC */
#ifndef NO_CRYPT_BENCHMARK
static byte mRtcInitDone = 0;
static int mRtcSec = 0;
const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(0); /**< Declaring an instance of nrf_drv_rtc for RTC0. */
#endif /* !NO_CRYPT_BENCHMARK */
/* AES */
#if !defined(NO_AES) && !defined(SOFTDEVICE_PRESENT)
static byte mAesInitDone = 0;
#endif
/** @brief Function for getting vector of random numbers.
*
* @param[out] p_buff Pointer to unit8_t buffer for storing the bytes.
* @param[in] length Number of bytes to take from pool and place in p_buff.
*
* @retval 0 = Success, else error
*/
int nrf51_random_generate(byte* output, word32 size)
{
int remaining = size, length, pos = 0;
uint8_t available;
uint32_t err_code;
/* Make sure RNG is running */
err_code = nrf_drv_rng_init(NULL);
if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
return -1;
}
while (remaining > 0) {
err_code = nrf_drv_rng_bytes_available(&available);
if (err_code == NRF_SUCCESS) {
length = (remaining < available) ? remaining : available;
if (length > 0) {
err_code = nrf_drv_rng_rand(&output[pos], length);
remaining -= length;
pos += length;
}
}
if (err_code != NRF_SUCCESS) {
break;
}
}
return (err_code == NRF_SUCCESS) ? 0 : -1;
}
#if !defined(NO_AES) && defined(WOLFSSL_NRF51_AES)
#ifdef SOFTDEVICE_PRESENT
static const byte* nRF51AesKey = NULL;
#endif
int nrf51_aes_set_key(const byte* key)
{
#ifdef SOFTDEVICE_PRESENT
nRF51AesKey = key;
#else
if (!mAesInitDone) {
nrf_ecb_init();
mAesInitDone = 1;
}
nrf_ecb_set_key(key);
#endif
return 0;
}
int nrf51_aes_encrypt(const byte* in, const byte* key, word32 rounds, byte* out)
{
int ret;
uint32_t err_code = 0;
#ifdef SOFTDEVICE_PRESENT
nrf_ecb_hal_data_t ecb_hal_data;
#endif
/* Set key */
ret = nrf51_aes_set_key(key);
if (ret != 0) {
return ret;
}
#ifdef SOFTDEVICE_PRESENT
/* Define ECB record */
XMEMCPY(ecb_hal_data.key, nRF51AesKey, SOC_ECB_KEY_LENGTH);
XMEMCPY(ecb_hal_data.cleartext, in, SOC_ECB_CLEARTEXT_LENGTH);
XMEMSET(ecb_hal_data.ciphertext, 0, SOC_ECB_CIPHERTEXT_LENGTH);
/* Perform block encrypt */
err_code = sd_ecb_block_encrypt(&ecb_hal_data);
if (err_code != NRF_SUCCESS) {
return -1;
}
/* Grab result */
XMEMCPY(out, ecb_hal_data.ciphertext, SOC_ECB_CIPHERTEXT_LENGTH);
#else
err_code = nrf_ecb_crypt(out, in);
err_code = err_code ? 0 : -1;
#endif
return err_code;
}
#endif /* !NO_AES && WOLFSSL_NRF51_AES */
#ifndef NO_CRYPT_BENCHMARK
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
if (int_type == NRF_DRV_RTC_INT_COMPARE0)
{
mRtcSec++;
nrf_drv_rtc_counter_clear(&rtc);
nrf_drv_rtc_int_enable(&rtc, RTC_CHANNEL_INT_MASK(0));
#ifdef BSP_LED_0
nrf_gpio_pin_toggle(BSP_LED_0);
#endif
}
}
static void rtc_config(void)
{
uint32_t err_code;
// Start the internal LFCLK XTAL oscillator
err_code = nrf_drv_clock_init(NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_clock_lfclk_request();
// Initialize RTC instance
err_code = nrf_drv_rtc_init(&rtc, NULL, rtc_handler);
APP_ERROR_CHECK(err_code);
// Enable tick event
nrf_drv_rtc_tick_enable(&rtc, false);
// Set compare channel to trigger interrupt after 1 seconds
err_code = nrf_drv_rtc_cc_set(&rtc, 0, RTC0_CONFIG_FREQUENCY, true);
APP_ERROR_CHECK(err_code);
// Power on RTC instance
nrf_drv_rtc_enable(&rtc);
}
static int rtc_get_ms(void)
{
/* Prescaler is 12-bit for COUNTER: frequency = (32768/(PRESCALER+1)) */
int frequency = (32768 / (rtc_prescaler_get(rtc.p_reg) + 1));
int counter = nrf_drv_rtc_counter_get(&rtc);
/* Convert with rounding frequency to milliseconds */
return ((counter * 1000) + (frequency / 2) ) / frequency;
}
double current_time(int reset)
{
double time;
if (!mRtcInitDone) {
rtc_config();
mRtcInitDone = 1;
}
time = mRtcSec;
time += (double)rtc_get_ms() / 1000;
return time;
}
#endif /* !NO_CRYPT_BENCHMARK */
#endif /* WOLFSSL_NRF51 */

File diff suppressed because it is too large Load diff

View file

@ -1,132 +0,0 @@
# ST Ports
Support for the STM32 L4, F1, F2, F4 and F7 on-board crypto hardware acceleration for symmetric AES (ECB/CBC/CTR/GCM) and MD5/SHA1/SHA224/SHA256.
Support for the STSAFE-A100 crypto hardware accelerator co-processor via I2C for ECC supporting NIST or Brainpool 256-bit and 384-bit curves. It requires the ST-Safe SDK including wolf stsafe_interface.c/.h files. Please contact ST for these.
For details see our [wolfSSL ST](https://www.wolfssl.com/docs/stm32/) page.
## STM32 Symmetric Acceleration
We support using the STM32 CubeMX and Standard Peripheral Library.
### Building
To enable support define one of the following:
```
#define WOLFSSL_STM32L4
#define WOLFSSL_STM32F1
#define WOLFSSL_STM32F2
#define WOLFSSL_STM32F4
#define WOLFSSL_STM32F7
```
To use CubeMX define `WOLFSSL_STM32_CUBEMX` otherwise StdPeriLib is used.
To disable portions of the hardware acceleration you can optionally define:
```
#define NO_STM32_RNG
#define NO_STM32_CRYPTO
#define NO_STM32_HASH
```
### Coding
In your application you must include <wolfssl/wolfcrypt/settings.h> before any other wolfSSL headers. If building the sources directly we recommend defining `WOLFSSL_USER_SETTINGS` and adding your own `user_settings.h` file. You can find a good reference for this in `IDE/GCC-ARM/Header/user_settings.h`.
### Benchmarks
See our [benchmarks](https://www.wolfssl.com/docs/benchmarks/) on the wolfSSL website.
## STSAFE-A100 ECC Acceleration
Using the wolfSSL PK callbacks and the reference ST Safe reference API's we support an ECC only cipher suite such as ECDHE-ECDSA-AES128-SHA256 for TLS client or server.
At the wolfCrypt level we also support ECC native API's for `wc_ecc_*` using the ST-Safe.
### Building
`./configure --enable-pkcallbacks CFLAGS="-DWOLFSSL_STSAFEA100"`
or
`#define HAVE_PK_CALLBACKS`
`#define WOLFSSL_STSAFEA100`
### Coding
Setup the PK callbacks for TLS using:
```
/* Setup PK Callbacks for STSAFE-A100 */
WOLFSSL_CTX* ctx;
wolfSSL_CTX_SetEccKeyGenCb(ctx, SSL_STSAFE_CreateKeyCb);
wolfSSL_CTX_SetEccSignCb(ctx, SSL_STSAFE_SignCertificateCb);
wolfSSL_CTX_SetEccVerifyCb(ctx, SSL_STSAFE_VerifyPeerCertCb);
wolfSSL_CTX_SetEccSharedSecretCb(ctx, SSL_STSAFE_SharedSecretCb);
wolfSSL_CTX_SetDevId(ctx, 0); /* enables wolfCrypt `wc_ecc_*` ST-Safe use */
```
The reference STSAFE-A100 PK callback functions are located in the `wolfcrypt/src/port/st/stsafe.c` file.
Adding a custom context to the callbacks:
```
/* Setup PK Callbacks context */
WOLFSSL* ssl;
void* myOwnCtx;
wolfSSL_SetEccKeyGenCtx(ssl, myOwnCtx);
wolfSSL_SetEccVerifyCtx(ssl, myOwnCtx);
wolfSSL_SetEccSignCtx(ssl, myOwnCtx);
wolfSSL_SetEccSharedSecretCtx(ssl, myOwnCtx);
```
### Benchmarks and Memory Use
Software only implementation (STM32L4 120Mhz, Cortex-M4, Fast Math):
```
ECDHE 256 key gen SW 4 ops took 1.278 sec, avg 319.500 ms, 3.130 ops/sec
ECDHE 256 agree SW 4 ops took 1.306 sec, avg 326.500 ms, 3.063 ops/sec
ECDSA 256 sign SW 4 ops took 1.298 sec, avg 324.500 ms, 3.082 ops/sec
ECDSA 256 verify SW 2 ops took 1.283 sec, avg 641.500 ms, 1.559 ops/sec
```
Memory Use:
```
Peak Stack: 18456
Peak Heap: 2640
Total: 21096
```
STSAFE-A100 acceleration:
```
ECDHE 256 key gen HW 8 ops took 1.008 sec, avg 126.000 ms, 7.937 ops/sec
ECDHE 256 agree HW 6 ops took 1.051 sec, avg 175.167 ms, 5.709 ops/sec
ECDSA 256 sign HW 14 ops took 1.161 sec, avg 82.929 ms, 12.059 ops/sec
ECDSA 256 verify HW 8 ops took 1.184 sec, avg 148.000 ms, 6.757 ops/sec
```
Memory Use:
```
Peak Stack: 9592
Peak Heap: 170
Total: 9762
```
## Support
Email us at [support@wolfssl.com](mailto:support@wolfssl.com).

View file

@ -1,879 +0,0 @@
/* stm32.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* Generic STM32 Hashing Function */
/* Supports CubeMX HAL or Standard Peripheral Library */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/port/st/stm32.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#ifndef NO_AES
#include <wolfssl/wolfcrypt/aes.h>
#endif
#ifdef STM32_HASH
#ifdef WOLFSSL_STM32L4
#define HASH_STR_NBW HASH_STR_NBLW
#endif
/* User can override STM32_HASH_CLOCK_ENABLE and STM32_HASH_CLOCK_DISABLE */
#ifndef STM32_HASH_CLOCK_ENABLE
static WC_INLINE void wc_Stm32_Hash_Clock_Enable(STM32_HASH_Context* stmCtx)
{
#ifdef WOLFSSL_STM32_CUBEMX
__HAL_RCC_HASH_CLK_ENABLE();
#else
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, ENABLE);
#endif
(void)stmCtx;
}
#define STM32_HASH_CLOCK_ENABLE(ctx) wc_Stm32_Hash_Clock_Enable(ctx)
#endif
#ifndef STM32_HASH_CLOCK_DISABLE
static WC_INLINE void wc_Stm32_Hash_Clock_Disable(STM32_HASH_Context* stmCtx)
{
#ifdef WOLFSSL_STM32_CUBEMX
__HAL_RCC_HASH_CLK_DISABLE();
#else
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_HASH, DISABLE);
#endif
(void)stmCtx;
}
#define STM32_HASH_CLOCK_DISABLE(ctx) wc_Stm32_Hash_Clock_Disable(ctx)
#endif
/* STM32 Port Internal Functions */
static WC_INLINE void wc_Stm32_Hash_SaveContext(STM32_HASH_Context* ctx)
{
int i;
/* save context registers */
ctx->HASH_IMR = HASH->IMR;
ctx->HASH_STR = HASH->STR;
ctx->HASH_CR = HASH->CR;
for (i=0; i<HASH_CR_SIZE; i++) {
ctx->HASH_CSR[i] = HASH->CSR[i];
}
}
static WC_INLINE int wc_Stm32_Hash_RestoreContext(STM32_HASH_Context* ctx)
{
int i;
if (ctx->HASH_CR != 0) {
/* restore context registers */
HASH->IMR = ctx->HASH_IMR;
HASH->STR = ctx->HASH_STR;
HASH->CR = ctx->HASH_CR;
/* Initialize the hash processor */
HASH->CR |= HASH_CR_INIT;
/* continue restoring context registers */
for (i=0; i<HASH_CR_SIZE; i++) {
HASH->CSR[i] = ctx->HASH_CSR[i];
}
return 1;
}
return 0;
}
static WC_INLINE void wc_Stm32_Hash_GetDigest(byte* hash, int digestSize)
{
word32 digest[HASH_MAX_DIGEST/sizeof(word32)];
/* get digest result */
digest[0] = HASH->HR[0];
digest[1] = HASH->HR[1];
digest[2] = HASH->HR[2];
digest[3] = HASH->HR[3];
if (digestSize >= 20) {
digest[4] = HASH->HR[4];
#ifdef HASH_DIGEST
if (digestSize >= 28) {
digest[5] = HASH_DIGEST->HR[5];
digest[6] = HASH_DIGEST->HR[6];
if (digestSize == 32)
digest[7] = HASH_DIGEST->HR[7];
}
#endif
}
ByteReverseWords(digest, digest, digestSize);
XMEMCPY(hash, digest, digestSize);
}
/* STM32 Port Exposed Functions */
static WC_INLINE int wc_Stm32_Hash_WaitDone(void)
{
/* wait until hash hardware is not busy */
int timeout = 0;
while ((HASH->SR & HASH_SR_BUSY) && ++timeout < STM32_HASH_TIMEOUT) {
}
/* verify timeout did not occur */
if (timeout >= STM32_HASH_TIMEOUT) {
return WC_TIMEOUT_E;
}
return 0;
}
void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx)
{
/* clear context */
XMEMSET(stmCtx, 0, sizeof(STM32_HASH_Context));
}
int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo,
const byte* data, int len)
{
int ret = 0;
byte* local = (byte*)stmCtx->buffer;
int wroteToFifo = 0;
/* check that internal buffLen is valid */
if (stmCtx->buffLen >= STM32_HASH_REG_SIZE) {
return BUFFER_E;
}
/* turn on hash clock */
STM32_HASH_CLOCK_ENABLE(stmCtx);
/* restore hash context or init as new hash */
if (wc_Stm32_Hash_RestoreContext(stmCtx) == 0) {
/* reset the control register */
HASH->CR &= ~(HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE);
/* configure algorithm, mode and data type */
HASH->CR |= (algo | HASH_ALGOMODE_HASH | HASH_DATATYPE_8B);
/* reset HASH processor */
HASH->CR |= HASH_CR_INIT;
}
/* write 4-bytes at a time into FIFO */
while (len) {
word32 add = min(len, STM32_HASH_REG_SIZE - stmCtx->buffLen);
XMEMCPY(&local[stmCtx->buffLen], data, add);
stmCtx->buffLen += add;
data += add;
len -= add;
if (stmCtx->buffLen == STM32_HASH_REG_SIZE) {
wroteToFifo = 1;
HASH->DIN = *(word32*)stmCtx->buffer;
stmCtx->loLen += STM32_HASH_REG_SIZE;
stmCtx->buffLen = 0;
}
}
if (wroteToFifo) {
/* save hash state for next operation */
wc_Stm32_Hash_SaveContext(stmCtx);
}
/* turn off hash clock */
STM32_HASH_CLOCK_DISABLE(stmCtx);
return ret;
}
int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
byte* hash, int digestSize)
{
int ret = 0;
word32 nbvalidbitsdata = 0;
/* turn on hash clock */
STM32_HASH_CLOCK_ENABLE(stmCtx);
/* restore hash state */
wc_Stm32_Hash_RestoreContext(stmCtx);
/* finish reading any trailing bytes into FIFO */
if (stmCtx->buffLen > 0) {
HASH->DIN = *(word32*)stmCtx->buffer;
stmCtx->loLen += stmCtx->buffLen;
}
/* calculate number of valid bits in last word */
nbvalidbitsdata = 8 * (stmCtx->loLen % STM32_HASH_REG_SIZE);
HASH->STR &= ~HASH_STR_NBW;
HASH->STR |= nbvalidbitsdata;
/* start hash processor */
HASH->STR |= HASH_STR_DCAL;
/* wait for hash done */
ret = wc_Stm32_Hash_WaitDone();
if (ret == 0) {
/* read message digest */
wc_Stm32_Hash_GetDigest(hash, digestSize);
}
/* turn off hash clock */
STM32_HASH_CLOCK_DISABLE(stmCtx);
return ret;
}
#endif /* STM32_HASH */
#ifdef STM32_CRYPTO
#ifndef NO_AES
#ifdef WOLFSSL_STM32_CUBEMX
int wc_Stm32_Aes_Init(Aes* aes, CRYP_HandleTypeDef* hcryp)
{
int ret;
word32 keySize;
ret = wc_AesGetKeySize(aes, &keySize);
if (ret != 0)
return ret;
XMEMSET(hcryp, 0, sizeof(CRYP_HandleTypeDef));
switch (keySize) {
case 16: /* 128-bit key */
hcryp->Init.KeySize = CRYP_KEYSIZE_128B;
break;
#ifdef CRYP_KEYSIZE_192B
case 24: /* 192-bit key */
hcryp->Init.KeySize = CRYP_KEYSIZE_192B;
break;
#endif
case 32: /* 256-bit key */
hcryp->Init.KeySize = CRYP_KEYSIZE_256B;
break;
default:
break;
}
hcryp->Instance = CRYP;
hcryp->Init.DataType = CRYP_DATATYPE_8B;
hcryp->Init.pKey = (STM_CRYPT_TYPE*)aes->key;
#ifdef STM32_HAL_V2
hcryp->Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
#endif
return 0;
}
#else /* STD_PERI_LIB */
int wc_Stm32_Aes_Init(Aes* aes, CRYP_InitTypeDef* cryptInit,
CRYP_KeyInitTypeDef* keyInit)
{
int ret;
word32 keySize;
word32* aes_key;
ret = wc_AesGetKeySize(aes, &keySize);
if (ret != 0)
return ret;
aes_key = aes->key;
/* crypto structure initialization */
CRYP_KeyStructInit(keyInit);
CRYP_StructInit(cryptInit);
/* load key into correct registers */
switch (keySize) {
case 16: /* 128-bit key */
cryptInit->CRYP_KeySize = CRYP_KeySize_128b;
keyInit->CRYP_Key2Left = aes_key[0];
keyInit->CRYP_Key2Right = aes_key[1];
keyInit->CRYP_Key3Left = aes_key[2];
keyInit->CRYP_Key3Right = aes_key[3];
break;
case 24: /* 192-bit key */
cryptInit->CRYP_KeySize = CRYP_KeySize_192b;
keyInit->CRYP_Key1Left = aes_key[0];
keyInit->CRYP_Key1Right = aes_key[1];
keyInit->CRYP_Key2Left = aes_key[2];
keyInit->CRYP_Key2Right = aes_key[3];
keyInit->CRYP_Key3Left = aes_key[4];
keyInit->CRYP_Key3Right = aes_key[5];
break;
case 32: /* 256-bit key */
cryptInit->CRYP_KeySize = CRYP_KeySize_256b;
keyInit->CRYP_Key0Left = aes_key[0];
keyInit->CRYP_Key0Right = aes_key[1];
keyInit->CRYP_Key1Left = aes_key[2];
keyInit->CRYP_Key1Right = aes_key[3];
keyInit->CRYP_Key2Left = aes_key[4];
keyInit->CRYP_Key2Right = aes_key[5];
keyInit->CRYP_Key3Left = aes_key[6];
keyInit->CRYP_Key3Right = aes_key[7];
break;
default:
break;
}
cryptInit->CRYP_DataType = CRYP_DataType_8b;
return 0;
}
#endif /* WOLFSSL_STM32_CUBEMX */
#endif /* !NO_AES */
#endif /* STM32_CRYPTO */
#ifdef WOLFSSL_STM32_PKA
#include <stdint.h>
#include <stm32wbxx_hal_conf.h>
#include <stm32wbxx_hal_pka.h>
extern PKA_HandleTypeDef hpka;
/* Reverse array in memory (in place) */
#ifdef HAVE_ECC
#include <wolfssl/wolfcrypt/ecc.h>
/* convert from mp_int to STM32 PKA HAL integer, as array of bytes of size sz.
* if mp_int has less bytes than sz, add zero bytes at most significant byte positions.
* This is when for example modulus is 32 bytes (P-256 curve)
* and mp_int has only 31 bytes, we add leading zeros
* so that result array has 32 bytes, same as modulus (sz).
*/
static int stm32_get_from_mp_int(uint8_t *dst, mp_int *a, int sz)
{
int res;
int szbin;
int offset;
if (!a || !dst || (sz < 0))
return -1;
/* check how many bytes are in the mp_int */
szbin = mp_unsigned_bin_size(a);
if ((szbin < 0) || (szbin > sz))
return -1;
/* compute offset from dst */
offset = sz - szbin;
if (offset < 0)
offset = 0;
if (offset > sz)
offset = sz;
/* add leading zeroes */
if (offset)
XMEMSET(dst, 0, offset);
/* convert mp_int to array of bytes */
res = mp_to_unsigned_bin(a, dst + offset);
return res;
}
/* ECC specs in lsbyte at lowest address format for direct use by STM32_PKA PKHA driver functions */
#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
#define ECC192
#endif
#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
#define ECC224
#endif
#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
#define ECC256
#endif
#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
#define ECC384
#endif
/* STM32 PKA supports up to 640bit numbers */
#define STM32_MAX_ECC_SIZE (80)
/* P-192 */
#ifdef ECC192
#define ECC192_KEYSIZE (24)
static const uint8_t stm32_ecc192_prime[ECC192_KEYSIZE] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const uint32_t stm32_ecc192_coef_sign = 1U;
static const uint8_t stm32_ecc192_coef[ECC192_KEYSIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
};
static const uint8_t stm32_ecc192_pointX[ECC192_KEYSIZE] = {
0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6,
0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00,
0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12
};
const uint8_t stm32_ecc192_pointY[ECC192_KEYSIZE] = {
0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78,
0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5,
0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11
};
const uint8_t stm32_ecc192_order[ECC192_KEYSIZE] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36,
0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31
};
const uint32_t stm32_ecc192_cofactor = 1U;
#endif /* ECC192 */
/* P-224 */
#ifdef ECC224
#define ECC224_KEYSIZE (28)
static const uint8_t stm32_ecc224_prime[ECC224_KEYSIZE] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01
};
static const uint32_t stm32_ecc224_coef_sign = 1U;
static const uint8_t stm32_ecc224_coef[ECC224_KEYSIZE] = {
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, 0x03
};
static const uint8_t stm32_ecc224_pointX[ECC224_KEYSIZE] = {
0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F,
0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3,
0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
0x11, 0x5C, 0x1D, 0x21
};
const uint8_t stm32_ecc224_pointY[ECC224_KEYSIZE] = {
0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB,
0x4C, 0x22, 0xDF, 0xE6, 0xCD, 0x43, 0x75, 0xA0,
0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99,
0x85, 0x00, 0x7E, 0x34
};
const uint8_t stm32_ecc224_order[ECC224_KEYSIZE] = {
};
const uint32_t stm32_ecc224_cofactor = 1U;
#endif /* ECC224 */
/* P-256 */
#ifdef ECC256
#define ECC256_KEYSIZE (32)
static const uint8_t stm32_ecc256_prime[ECC256_KEYSIZE] = {
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const uint32_t stm32_ecc256_coef_sign = 1U;
static const uint8_t stm32_ecc256_coef[ECC256_KEYSIZE] = {
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, 0x03
};
static const uint8_t stm32_ecc256_pointX[ECC256_KEYSIZE] = {
0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2,
0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96
};
const uint8_t stm32_ecc256_pointY[ECC256_KEYSIZE] = {
0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b,
0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5
};
const uint8_t stm32_ecc256_order[ECC256_KEYSIZE] = {
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84,
0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51
};
const uint32_t stm32_ecc256_cofactor = 1U;
#endif /* ECC256 */
/* P-384 */
#ifdef ECC384
#define ECC384_KEYSIZE (48)
static const uint8_t stm32_ecc384_prime[ECC384_KEYSIZE] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF
};
static const uint32_t stm32_ecc384_coef_sign = 1U;
static const uint8_t stm32_ecc384_coef[ECC384_KEYSIZE] = {
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, 0x03
};
static const uint8_t stm32_ecc384_pointX[ECC384_KEYSIZE] = {
0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37,
0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74,
0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38,
0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C,
0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
};
const uint8_t stm32_ecc384_pointY[ECC384_KEYSIZE] = {
0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F,
0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29,
0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0,
0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D,
0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F,
};
const uint8_t stm32_ecc384_order[ECC384_KEYSIZE] = {
};
const uint32_t stm32_ecc384_cofactor = 1U;
#endif /* ECC384 */
static int stm32_get_ecc_specs(const uint8_t **prime, const uint8_t **coef,
const uint32_t **coef_sign, const uint8_t **GenPointX, const uint8_t **GenPointY,
const uint8_t **order, int size)
{
switch(size) {
case 32:
*prime = stm32_ecc256_prime;
*coef = stm32_ecc256_coef;
*GenPointX = stm32_ecc256_pointX;
*GenPointY = stm32_ecc256_pointY;
*coef_sign = &stm32_ecc256_coef_sign;
*order = stm32_ecc256_order;
break;
#ifdef ECC224
case 28:
*prime = stm32_ecc224_prime;
*coef = stm32_ecc224_coef;
*GenPointX = stm32_ecc224_pointX;
*GenPointY = stm32_ecc224_pointY;
*coef_sign = &stm32_ecc224_coef;
break;
#endif
#ifdef ECC192
case 24:
*prime = stm32_ecc192_prime;
*coef = stm32_ecc192_coef;
*GenPointX = stm32_ecc192_pointX;
*GenPointY = stm32_ecc192_pointY;
*coef_sign = &stm32_ecc192_coef;
break;
#endif
#ifdef ECC384
case 48:
*prime = stm32_ecc384_prime;
*coef = stm32_ecc384_coef;
*GenPointX = stm32_ecc384_pointX;
*GenPointY = stm32_ecc384_pointY;
*coef_sign = &stm32_ecc384_coef;
break;
#endif
default:
return -1;
}
return 0;
}
/**
Perform a point multiplication (timing resistant)
k The scalar to multiply by
G The base point
R [out] Destination for kG
modulus The modulus of the field the ECC curve is in
map Boolean whether to map back to affine or not
(1==map, 0 == leave in projective)
return MP_OKAY on success
*/
int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int *modulus, int map, void* heap)
{
PKA_ECCMulInTypeDef pka_mul;
PKA_ECCMulOutTypeDef pka_mul_res;
uint8_t size;
int szModulus;
int szkbin;
int status;
int res;
uint8_t Gxbin[STM32_MAX_ECC_SIZE];
uint8_t Gybin[STM32_MAX_ECC_SIZE];
uint8_t kbin[STM32_MAX_ECC_SIZE];
uint8_t PtXbin[STM32_MAX_ECC_SIZE];
uint8_t PtYbin[STM32_MAX_ECC_SIZE];
const uint8_t *prime, *coef, *gen_x, *gen_y, *order;
const uint32_t *coef_sign;
(void)a;
(void)heap;
XMEMSET(&pka_mul, 0x00, sizeof(PKA_ECCMulInTypeDef));
XMEMSET(&pka_mul_res, 0x00, sizeof(PKA_ECCMulOutTypeDef));
pka_mul_res.ptX = PtXbin;
pka_mul_res.ptY = PtYbin;
if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
return ECC_BAD_ARG_E;
}
szModulus = mp_unsigned_bin_size(modulus);
szkbin = mp_unsigned_bin_size(k);
res = stm32_get_from_mp_int(kbin, k, szkbin);
if (res == MP_OKAY)
res = stm32_get_from_mp_int(Gxbin, G->x, szModulus);
if (res == MP_OKAY)
res = stm32_get_from_mp_int(Gybin, G->y, szModulus);
if (res != MP_OKAY)
return res;
size = (uint8_t)szModulus;
/* find STM32_PKA friendly parameters for the selected curve */
if (0 != stm32_get_ecc_specs(&prime, &coef, &coef_sign, &gen_x, &gen_y, &order, size)) {
return ECC_BAD_ARG_E;
}
(void)order;
pka_mul.modulusSize = szModulus;
pka_mul.coefSign = *coef_sign;
pka_mul.coefA = coef;
pka_mul.modulus = prime;
pka_mul.pointX = Gxbin;
pka_mul.pointY = Gybin;
pka_mul.scalarMulSize = size;
pka_mul.scalarMul = kbin;
status = HAL_PKA_ECCMul(&hpka, &pka_mul, HAL_MAX_DELAY);
if (status != HAL_OK) {
return WC_HW_E;
}
pka_mul_res.ptX = Gxbin;
pka_mul_res.ptY = Gybin;
HAL_PKA_ECCMul_GetResult(&hpka, &pka_mul_res);
res = mp_read_unsigned_bin(R->x, Gxbin, size);
if (res == MP_OKAY) {
res = mp_read_unsigned_bin(R->y, Gybin, size);
#ifndef WOLFSSL_SP_MATH
/* if k is negative, we compute the multiplication with abs(-k)
* with result (x, y) and modify the result to (x, -y)
*/
R->y->sign = k->sign;
#endif
}
if (res == MP_OKAY)
res = mp_set(R->z, 1);
HAL_PKA_RAMReset(&hpka);
return res;
}
int stm32_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
word32 hashlen, int* res, ecc_key* key)
{
PKA_ECDSAVerifInTypeDef pka_ecc;
uint8_t size;
int szModulus;
int szrbin;
int status;
uint8_t Rbin[STM32_MAX_ECC_SIZE];
uint8_t Sbin[STM32_MAX_ECC_SIZE];
uint8_t Qxbin[STM32_MAX_ECC_SIZE];
uint8_t Qybin[STM32_MAX_ECC_SIZE];
uint8_t Hashbin[STM32_MAX_ECC_SIZE];
uint8_t privKeybin[STM32_MAX_ECC_SIZE];
const uint8_t *prime, *coef, *gen_x, *gen_y, *order;
const uint32_t *coef_sign;
XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSAVerifInTypeDef));
if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL) {
return ECC_BAD_ARG_E;
}
*res = 0;
szModulus = mp_unsigned_bin_size(key->pubkey.x);
szrbin = mp_unsigned_bin_size(r);
status = stm32_get_from_mp_int(Rbin, r, szrbin);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(Sbin, s, szrbin);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(Qxbin, key->pubkey.x, szModulus);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(Qybin, key->pubkey.y, szModulus);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(privKeybin, &key->k, szModulus);
if (status != MP_OKAY)
return status;
size = (uint8_t)szModulus;
/* find parameters for the selected curve */
if (0 != stm32_get_ecc_specs(&prime, &coef, &coef_sign, &gen_x, &gen_y, &order, size)) {
return ECC_BAD_ARG_E;
}
pka_ecc.primeOrderSize = size;
pka_ecc.modulusSize = size;
pka_ecc.coefSign = *coef_sign;
pka_ecc.coef = coef;
pka_ecc.modulus = prime;
pka_ecc.basePointX = gen_x;
pka_ecc.basePointY = gen_y;
pka_ecc.primeOrder = order;
pka_ecc.pPubKeyCurvePtX = Qxbin;
pka_ecc.pPubKeyCurvePtY = Qybin;
pka_ecc.RSign = Rbin;
pka_ecc.SSign = Sbin;
XMEMSET(Hashbin, 0, STM32_MAX_ECC_SIZE);
XMEMCPY(Hashbin + (size - hashlen), hash, hashlen);
pka_ecc.hash = Hashbin;
status = HAL_PKA_ECDSAVerif(&hpka, &pka_ecc, HAL_MAX_DELAY);
if (status != HAL_OK) {
HAL_PKA_RAMReset(&hpka);
return WC_HW_E;
}
*res = HAL_PKA_ECDSAVerif_IsValidSignature(&hpka);
HAL_PKA_RAMReset(&hpka);
return status;
}
int stm32_ecc_sign_hash_ex(const byte* hash, word32 hashlen, WC_RNG* rng,
ecc_key* key, mp_int *r, mp_int *s)
{
PKA_ECDSASignInTypeDef pka_ecc;
PKA_ECDSASignOutTypeDef pka_ecc_out;
int size;
int status;
mp_int gen_k;
mp_int order_mp;
uint8_t Keybin[STM32_MAX_ECC_SIZE];
uint8_t Intbin[STM32_MAX_ECC_SIZE];
uint8_t Rbin[STM32_MAX_ECC_SIZE];
uint8_t Sbin[STM32_MAX_ECC_SIZE];
uint8_t Hashbin[STM32_MAX_ECC_SIZE];
const uint8_t *prime, *coef, *gen_x, *gen_y, *order;
const uint32_t *coef_sign;
XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSASignInTypeDef));
XMEMSET(&pka_ecc, 0x00, sizeof(PKA_ECDSASignOutTypeDef));
if (r == NULL || s == NULL || hash == NULL || key == NULL) {
return ECC_BAD_ARG_E;
}
mp_init(&gen_k);
mp_init(&order_mp);
size = mp_unsigned_bin_size(key->pubkey.x);
status = stm32_get_from_mp_int(Keybin, &key->k, size);
if (status != MP_OKAY)
return status;
/* find parameters for the selected curve */
if (0 != stm32_get_ecc_specs(&prime, &coef, &coef_sign, &gen_x, &gen_y, &order, size)) {
return ECC_BAD_ARG_E;
}
status = mp_read_unsigned_bin(&order_mp, order, size);
if (status == MP_OKAY)
status = wc_ecc_gen_k(rng, size, &gen_k, &order_mp);
if (status == MP_OKAY)
status = stm32_get_from_mp_int(Intbin, &gen_k, size);
if (status != MP_OKAY)
return status;
pka_ecc.primeOrderSize = size;
pka_ecc.modulusSize = size;
pka_ecc.coefSign = *coef_sign;
pka_ecc.coef = coef;
pka_ecc.modulus = prime;
pka_ecc.basePointX = gen_x;
pka_ecc.basePointY = gen_y;
pka_ecc.primeOrder = order;
XMEMSET(Hashbin, 0, STM32_MAX_ECC_SIZE);
XMEMCPY(Hashbin + (size - hashlen), hash, hashlen);
pka_ecc.hash = Hashbin;
pka_ecc.integer = Intbin;
pka_ecc.privateKey = Keybin;
/* Assign R, S static buffers */
pka_ecc_out.RSign = Rbin;
pka_ecc_out.SSign = Sbin;
status = HAL_PKA_ECDSASign(&hpka, &pka_ecc, HAL_MAX_DELAY);
if (status != HAL_OK) {
HAL_PKA_RAMReset(&hpka);
return WC_HW_E;
}
HAL_PKA_ECDSASign_GetResult(&hpka, &pka_ecc_out, NULL);
status = mp_read_unsigned_bin(r, pka_ecc_out.RSign, size);
if (status == MP_OKAY)
status = mp_read_unsigned_bin(s, pka_ecc_out.SSign, size);
HAL_PKA_RAMReset(&hpka);
return status;
}
#endif /* HAVE_ECC */
#endif /* WOLFSSL_STM32_PKA */

View file

@ -1,566 +0,0 @@
/* stsafe.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <wolfssl/wolfcrypt/port/st/stsafe.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifndef STSAFE_INTERFACE_PRINTF
#define STSAFE_INTERFACE_PRINTF(...)
#endif
#ifdef WOLFSSL_STSAFEA100
int SSL_STSAFE_LoadDeviceCertificate(byte** pRawCertificate,
word32* pRawCertificateLen)
{
int err;
if (pRawCertificate == NULL || pRawCertificateLen == NULL) {
return BAD_FUNC_ARG;
}
#ifdef USE_STSAFE_VERBOSE
WOLFSSL_MSG("SSL_STSAFE_LoadDeviceCertificate");
#endif
/* Try reading device certificate from ST-SAFE Zone 0 */
err = stsafe_interface_read_device_certificate_raw(
pRawCertificate, (uint32_t*)pRawCertificateLen);
if (err == STSAFE_A_OK) {
#if 0
/* example for loading into WOLFSSL_CTX */
err = wolfSSL_CTX_use_certificate_buffer(ctx,
*pRawCertificate, *pRawCertificateLen, SSL_FILETYPE_ASN1);
if (err != WOLFSSL_SUCCESS) {
/* failed */
}
/* can free now */
XFREE(*pRawCertificate, NULL, DYNAMIC_TEMP_BUFFER);
*pRawCertificate = NULL;
#endif
}
else {
err = WC_HW_E;
}
return err;
}
#ifdef HAVE_PK_CALLBACKS
/**
* \brief Key Gen Callback (used by TLS server)
*/
int SSL_STSAFE_CreateKeyCb(WOLFSSL* ssl, ecc_key* key, word32 keySz,
int ecc_curve, void* ctx)
{
int err;
byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN];
StSafeA_KeySlotNumber slot;
StSafeA_CurveId curve_id;
(void)ssl;
(void)ctx;
#ifdef USE_STSAFE_VERBOSE
WOLFSSL_MSG("CreateKeyCb: STSAFE");
#endif
/* get curve */
curve_id = stsafe_get_ecc_curve_id(ecc_curve);
/* generate new ephemeral key on device */
err = stsafe_interface_create_key(&slot, curve_id, (uint8_t*)&pubKeyRaw[0]);
if (err != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", err);
#endif
err = WC_HW_E;
return err;
}
/* load generated public key into key, used by wolfSSL */
err = wc_ecc_import_unsigned(key, &pubKeyRaw[0], &pubKeyRaw[keySz],
NULL, ecc_curve);
return err;
}
/**
* \brief Verify Peer Cert Callback.
*/
int SSL_STSAFE_VerifyPeerCertCb(WOLFSSL* ssl,
const unsigned char* sig, unsigned int sigSz,
const unsigned char* hash, unsigned int hashSz,
const unsigned char* keyDer, unsigned int keySz,
int* result, void* ctx)
{
int err;
byte sigRS[STSAFE_MAX_SIG_LEN];
byte *r, *s;
word32 r_len = STSAFE_MAX_SIG_LEN/2, s_len = STSAFE_MAX_SIG_LEN/2;
byte pubKeyX[STSAFE_MAX_PUBKEY_RAW_LEN/2];
byte pubKeyY[STSAFE_MAX_PUBKEY_RAW_LEN/2];
word32 pubKeyX_len = sizeof(pubKeyX);
word32 pubKeyY_len = sizeof(pubKeyY);
ecc_key key;
word32 inOutIdx = 0;
StSafeA_CurveId curve_id;
int ecc_curve;
(void)ssl;
(void)ctx;
#ifdef USE_STSAFE_VERBOSE
WOLFSSL_MSG("VerifyPeerCertCB: STSAFE");
#endif
err = wc_ecc_init(&key);
if (err != 0) {
return err;
}
/* Decode the public key */
err = wc_EccPublicKeyDecode(keyDer, &inOutIdx, &key, keySz);
if (err == 0) {
/* Extract Raw X and Y coordinates of the public key */
err = wc_ecc_export_public_raw(&key, pubKeyX, &pubKeyX_len,
pubKeyY, &pubKeyY_len);
}
if (err == 0) {
int key_sz;
/* determine curve */
ecc_curve = key.dp->id;
curve_id = stsafe_get_ecc_curve_id(ecc_curve);
key_sz = stsafe_get_key_size(curve_id);
/* Extract R and S from signature */
XMEMSET(sigRS, 0, sizeof(sigRS));
r = &sigRS[0];
s = &sigRS[key_sz];
err = wc_ecc_sig_to_rs(sig, sigSz, r, &r_len, s, &s_len);
(void)r_len;
(void)s_len;
}
if (err == 0) {
/* Verify signature */
err = stsafe_interface_verify(curve_id, (uint8_t*)hash, sigRS,
pubKeyX, pubKeyY, (int32_t*)result);
if (err != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_verify error: %d\n", err);
#endif
err = WC_HW_E;
}
}
wc_ecc_free(&key);
return err;
}
/**
* \brief Sign Certificate Callback.
*/
int SSL_STSAFE_SignCertificateCb(WOLFSSL* ssl, const byte* in,
word32 inSz, byte* out, word32* outSz,
const byte* key, word32 keySz, void* ctx)
{
int err;
byte digest[STSAFE_MAX_KEY_LEN];
byte sigRS[STSAFE_MAX_SIG_LEN];
byte *r, *s;
StSafeA_CurveId curve_id;
int key_sz;
(void)ssl;
(void)ctx;
#ifdef USE_STSAFE_VERBOSE
WOLFSSL_MSG("SignCertificateCb: STSAFE");
#endif
curve_id = stsafe_get_curve_mode();
key_sz = stsafe_get_key_size(curve_id);
/* Build input digest */
if (inSz > key_sz)
inSz = key_sz;
XMEMSET(&digest[0], 0, sizeof(digest));
XMEMCPY(&digest[key_sz - inSz], in, inSz);
/* Sign using slot 0: Result is R then S */
/* Sign will always use the curve type in slot 0 (the TLS curve needs to match) */
XMEMSET(sigRS, 0, sizeof(sigRS));
err = stsafe_interface_sign(STSAFE_A_SLOT_0, curve_id, digest, sigRS);
if (err != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_sign error: %d\n", err);
#endif
err = WC_HW_E;
return err;
}
/* Convert R and S to signature */
r = &sigRS[0];
s = &sigRS[key_sz];
err = wc_ecc_rs_raw_to_sig((const byte*)r, key_sz, (const byte*)s, key_sz,
out, outSz);
if (err != 0) {
#ifdef USE_STSAFE_VERBOSE
WOLFSSL_MSG("Error converting RS to Signature");
#endif
}
return err;
}
/**
* \brief Create pre master secret using peer's public key and self private key.
*/
int SSL_STSAFE_SharedSecretCb(WOLFSSL* ssl, ecc_key* otherKey,
unsigned char* pubKeyDer, unsigned int* pubKeySz,
unsigned char* out, unsigned int* outlen,
int side, void* ctx)
{
int err;
byte otherKeyX[STSAFE_MAX_KEY_LEN];
byte otherKeyY[STSAFE_MAX_KEY_LEN];
word32 otherKeyX_len = sizeof(otherKeyX);
word32 otherKeyY_len = sizeof(otherKeyY);
byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN];
StSafeA_KeySlotNumber slot;
StSafeA_CurveId curve_id;
ecc_key tmpKey;
int ecc_curve;
int key_sz;
(void)ssl;
(void)ctx;
#ifdef USE_STSAFE_VERBOSE
WOLFSSL_MSG("SharedSecretCb: STSAFE");
#endif
err = wc_ecc_init(&tmpKey);
if (err != 0) {
return err;
}
/* set curve */
ecc_curve = otherKey->dp->id;
curve_id = stsafe_get_ecc_curve_id(ecc_curve);
key_sz = stsafe_get_key_size(curve_id);
/* for client: create and export public key */
if (side == WOLFSSL_CLIENT_END) {
/* Export otherKey raw X and Y */
err = wc_ecc_export_public_raw(otherKey,
&otherKeyX[0], (word32*)&otherKeyX_len,
&otherKeyY[0], (word32*)&otherKeyY_len);
if (err != 0) {
return err;
}
err = stsafe_interface_create_key(&slot, curve_id, (uint8_t*)&pubKeyRaw[0]);
if (err != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", err);
#endif
err = WC_HW_E;
return err;
}
/* convert raw unsigned public key to X.963 format for TLS */
err = wc_ecc_init(&tmpKey);
if (err == 0) {
err = wc_ecc_import_unsigned(&tmpKey, &pubKeyRaw[0], &pubKeyRaw[key_sz],
NULL, ecc_curve);
if (err == 0) {
err = wc_ecc_export_x963(&tmpKey, pubKeyDer, pubKeySz);
}
wc_ecc_free(&tmpKey);
}
}
/* for server: import public key */
else if (side == WOLFSSL_SERVER_END) {
/* import peer's key and export as raw unsigned for hardware */
err = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &tmpKey, ecc_curve);
if (err == 0) {
err = wc_ecc_export_public_raw(&tmpKey, otherKeyX, &otherKeyX_len,
otherKeyY, &otherKeyY_len);
}
}
else {
err = BAD_FUNC_ARG;
}
wc_ecc_free(&tmpKey);
if (err != 0) {
return err;
}
/* Compute shared secret */
err = stsafe_interface_shared_secret(curve_id, &otherKeyX[0], &otherKeyY[0],
out, (int32_t*)outlen);
if (err != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_shared_secret error: %d\n", err);
#endif
err = WC_HW_E;
}
return err;
}
int SSL_STSAFE_SetupPkCallbacks(WOLFSSL_CTX* ctx)
{
wolfSSL_CTX_SetEccKeyGenCb(ctx, SSL_STSAFE_CreateKeyCb);
wolfSSL_CTX_SetEccSignCb(ctx, SSL_STSAFE_SignCertificateCb);
wolfSSL_CTX_SetEccVerifyCb(ctx, SSL_STSAFE_VerifyPeerCertCb);
wolfSSL_CTX_SetEccSharedSecretCb(ctx, SSL_STSAFE_SharedSecretCb);
wolfSSL_CTX_SetDevId(ctx, 0); /* enables wolfCrypt `wc_ecc_*` ST-Safe use */
return 0;
}
int SSL_STSAFE_SetupPkCallbackCtx(WOLFSSL* ssl, void* user_ctx)
{
wolfSSL_SetEccKeyGenCtx(ssl, user_ctx);
wolfSSL_SetEccSharedSecretCtx(ssl, user_ctx);
wolfSSL_SetEccSignCtx(ssl, user_ctx);
wolfSSL_SetEccVerifyCtx(ssl, user_ctx);
return 0;
}
#endif /* HAVE_PK_CALLBACKS */
#ifdef WOLF_CRYPTO_CB
int wolfSSL_STSAFE_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx)
{
int rc = CRYPTOCB_UNAVAILABLE;
wolfSTSAFE_CryptoCb_Ctx* stsCtx = (wolfSTSAFE_CryptoCb_Ctx*)ctx;
if (info == NULL || ctx == NULL)
return BAD_FUNC_ARG;
(void)devId;
(void)stsCtx;
if (info->algo_type == WC_ALGO_TYPE_SEED) {
/* use the STSAFE hardware for RNG seed */
#if !defined(WC_NO_RNG) && defined(USE_STSAFE_RNG_SEED)
while (info->seed.sz > 0) {
rc = stsafe_interface_getrandom(info->seed.seed, info->seed.sz);
if (rc < 0) {
return rc;
}
info->seed.seed += rc;
info->seed.sz -= rc;
}
rc = 0;
#else
rc = CRYPTOCB_UNAVAILABLE;
#endif
}
#ifdef HAVE_ECC
else if (info->algo_type == WC_ALGO_TYPE_PK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("STSAFE Pk: Type %d\n", info->pk.type);
#endif
if (info->pk.type == WC_PK_TYPE_EC_KEYGEN) {
byte pubKeyRaw[STSAFE_MAX_PUBKEY_RAW_LEN];
StSafeA_KeySlotNumber slot;
StSafeA_CurveId curve_id;
int ecc_curve, key_sz;
WOLFSSL_MSG("STSAFE: ECC KeyGen");
/* get curve */
ecc_curve = info->pk.eckg.curveId;
curve_id = stsafe_get_ecc_curve_id(ecc_curve);
key_sz = stsafe_get_key_size(curve_id);
/* generate new ephemeral key on device */
rc = stsafe_interface_create_key(&slot, curve_id,
(uint8_t*)pubKeyRaw);
if (rc != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_create_key error: %d\n", rc);
#endif
rc = WC_HW_E;
return rc;
}
/* load generated public key into key, used by wolfSSL */
rc = wc_ecc_import_unsigned(info->pk.eckg.key, pubKeyRaw,
&pubKeyRaw[key_sz], NULL, ecc_curve);
}
else if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
byte digest[STSAFE_MAX_KEY_LEN];
byte sigRS[STSAFE_MAX_SIG_LEN];
byte *r, *s;
StSafeA_CurveId curve_id;
word32 inSz = info->pk.eccsign.inlen;
int key_sz;
WOLFSSL_MSG("STSAFE: ECC Sign");
curve_id = stsafe_get_curve_mode();
key_sz = stsafe_get_key_size(curve_id);
/* truncate input to match key size */
if (inSz > key_sz)
inSz = key_sz;
/* Build input digest */
XMEMSET(&digest[0], 0, sizeof(digest));
XMEMCPY(&digest[key_sz - inSz], info->pk.eccsign.in, inSz);
/* Sign using slot 0: Result is R then S */
/* Sign will always use the curve type in slot 0
(the TLS curve needs to match) */
XMEMSET(sigRS, 0, sizeof(sigRS));
rc = stsafe_interface_sign(STSAFE_A_SLOT_0, curve_id,
(uint8_t*)info->pk.eccsign.in, sigRS);
if (rc != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_sign error: %d\n", rc);
#endif
rc = WC_HW_E;
return rc;
}
/* Convert R and S to signature */
r = &sigRS[0];
s = &sigRS[key_sz];
rc = wc_ecc_rs_raw_to_sig((const byte*)r, key_sz, (const byte*)s,
key_sz, info->pk.eccsign.out, info->pk.eccsign.outlen);
if (rc != 0) {
WOLFSSL_MSG("Error converting RS to Signature");
}
}
else if (info->pk.type == WC_PK_TYPE_ECDSA_VERIFY) {
byte sigRS[STSAFE_MAX_SIG_LEN];
byte *r, *s;
word32 r_len = STSAFE_MAX_SIG_LEN/2, s_len = STSAFE_MAX_SIG_LEN/2;
byte pubKeyX[STSAFE_MAX_PUBKEY_RAW_LEN/2];
byte pubKeyY[STSAFE_MAX_PUBKEY_RAW_LEN/2];
word32 pubKeyX_len = sizeof(pubKeyX);
word32 pubKeyY_len = sizeof(pubKeyY);
StSafeA_CurveId curve_id;
int ecc_curve, key_sz;
WOLFSSL_MSG("STSAFE: ECC Verify");
if (info->pk.eccverify.key == NULL)
return BAD_FUNC_ARG;
/* determine curve */
ecc_curve = info->pk.eccverify.key->dp->id;
curve_id = stsafe_get_ecc_curve_id(ecc_curve);
key_sz = stsafe_get_key_size(curve_id);
/* Extract Raw X and Y coordinates of the public key */
rc = wc_ecc_export_public_raw(info->pk.eccverify.key,
pubKeyX, &pubKeyX_len,
pubKeyY, &pubKeyY_len);
if (rc == 0) {
/* Extract R and S from signature */
XMEMSET(sigRS, 0, sizeof(sigRS));
r = &sigRS[0];
s = &sigRS[key_sz];
rc = wc_ecc_sig_to_rs(info->pk.eccverify.sig,
info->pk.eccverify.siglen, r, &r_len, s, &s_len);
(void)r_len;
(void)s_len;
}
if (rc == 0) {
/* Verify signature */
rc = stsafe_interface_verify(curve_id,
(uint8_t*)info->pk.eccverify.hash, sigRS, pubKeyX, pubKeyY,
(int32_t*)info->pk.eccverify.res);
if (rc != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_verify error: %d\n", rc);
#endif
rc = WC_HW_E;
}
}
}
else if (info->pk.type == WC_PK_TYPE_ECDH) {
byte otherKeyX[STSAFE_MAX_KEY_LEN];
byte otherKeyY[STSAFE_MAX_KEY_LEN];
word32 otherKeyX_len = sizeof(otherKeyX);
word32 otherKeyY_len = sizeof(otherKeyY);
StSafeA_CurveId curve_id;
int ecc_curve;
WOLFSSL_MSG("STSAFE: PMS");
if (info->pk.ecdh.public_key == NULL)
return BAD_FUNC_ARG;
/* get curve */
ecc_curve = info->pk.ecdh.public_key->dp->id;
curve_id = stsafe_get_ecc_curve_id(ecc_curve);
/* Export otherKey raw X and Y */
rc = wc_ecc_export_public_raw(info->pk.ecdh.public_key,
&otherKeyX[0], (word32*)&otherKeyX_len,
&otherKeyY[0], (word32*)&otherKeyY_len);
if (rc == 0) {
/* Compute shared secret */
*info->pk.ecdh.outlen = 0;
rc = stsafe_interface_shared_secret(curve_id,
otherKeyX, otherKeyY,
info->pk.ecdh.out, (int32_t*)info->pk.ecdh.outlen);
if (rc != STSAFE_A_OK) {
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("stsafe_interface_shared_secret error: %d\n", rc);
#endif
rc = WC_HW_E;
}
}
}
}
#endif /* HAVE_ECC */
/* need to return negative here for error */
if (rc != 0 && rc != CRYPTOCB_UNAVAILABLE) {
WOLFSSL_MSG("STSAFE: CryptoCb failed");
#ifdef USE_STSAFE_VERBOSE
STSAFE_INTERFACE_PRINTF("STSAFE: CryptoCb failed %d\n", rc);
#endif
rc = WC_HW_E;
}
return rc;
}
#endif /* WOLF_CRYPTO_CB */
#endif /* WOLFSSL_STSAFEA100 */

View file

@ -1,202 +0,0 @@
/* xil-aesgcm.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if !defined(NO_AES) && defined(WOLFSSL_XILINX_CRYPT)
#include <wolfssl/wolfcrypt/aes.h>
#ifdef HAVE_AESGCM
/* Make calls to Xilinx hardened AES-GCM crypto */
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
#include "xparameters.h"
enum {
AEAD_NONCE_SZ = 12,
AES_GCM_AUTH_SZ = 16, /* AES-GCM Auth Tag length */
};
int wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len, word32 kup)
{
XCsuDma_Config* con;
if (aes == NULL || key == NULL) {
return BAD_FUNC_ARG;
}
if (len != 32) {
WOLFSSL_MSG("Expecting a 256 bit key");
return BAD_FUNC_ARG;
}
if ((con = XCsuDma_LookupConfig(0)) == NULL) {
WOLFSSL_MSG("Failed to look up config");
return MEMORY_E;
}
/* XST_SUCCESS comes from Xilinx header file */
if (XCsuDma_CfgInitialize(&(aes->dma), con, con->BaseAddress) !=
XST_SUCCESS) {
WOLFSSL_MSG("Failed to initialize hardware");
return MEMORY_E;
}
aes->keylen = len;
aes->kup = kup;
XMEMCPY((byte*)(aes->key_init), key, len);
return 0;
}
int wc_AesGcmEncrypt(Aes* aes, byte* out,
const byte* in, word32 sz,
const byte* iv, word32 ivSz,
byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
byte* tmp;
byte scratch[AES_BLOCK_SIZE];
byte initalCounter[AES_BLOCK_SIZE];
if ((in == NULL && sz > 0) || iv == NULL || authTag == NULL ||
authTagSz > AES_GCM_AUTH_SZ) {
return BAD_FUNC_ARG;
}
if (ivSz != AEAD_NONCE_SZ) {
WOLFSSL_MSG("Expecting an IV size of 12");
return BAD_FUNC_ARG;
}
/* API expects that output is size of input + 16 byte tag. A temporary
* buffer is created to keep AES encrypt from writing over the end of
* out buffer. */
if (in != NULL) {
if (aes->keylen != 32) {
WOLFSSL_MSG("Expecting 256 bit AES key");
return BAD_FUNC_ARG;
}
tmp = (byte*)XMALLOC(sz + AES_GCM_AUTH_SZ, aes->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (tmp == NULL) {
return MEMORY_E;
}
XSecure_AesInitialize(&(aes->xilAes), &(aes->dma), aes->kup, (word32*)iv,
aes->key_init);
XSecure_AesEncryptData(&(aes->xilAes), tmp, in, sz);
XMEMCPY(out, tmp, sz);
XMEMCPY(authTag, tmp + sz, authTagSz);
XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
/* handle completing tag with any additional data */
if (authIn != NULL) {
/* @TODO avoid hashing out again since Xilinx call already does */
XMEMSET(initalCounter, 0, AES_BLOCK_SIZE);
XMEMCPY(initalCounter, iv, ivSz);
initalCounter[AES_BLOCK_SIZE - 1] = 1;
GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
wc_AesEncryptDirect(aes, scratch, initalCounter);
xorbuf(authTag, scratch, authTagSz);
}
return 0;
}
int wc_AesGcmDecrypt(Aes* aes, byte* out,
const byte* in, word32 sz,
const byte* iv, word32 ivSz,
const byte* authTag, word32 authTagSz,
const byte* authIn, word32 authInSz)
{
byte* tag;
byte buf[AES_GCM_AUTH_SZ];
byte scratch[AES_BLOCK_SIZE];
byte initalCounter[AES_BLOCK_SIZE];
if (in == NULL || iv == NULL || authTag == NULL ||
authTagSz < AES_GCM_AUTH_SZ) {
return BAD_FUNC_ARG;
}
if (ivSz != AEAD_NONCE_SZ) {
WOLFSSL_MSG("Expecting an IV size of 12");
return BAD_FUNC_ARG;
}
/* account for additional data */
if (authIn != NULL && authInSz > 0) {
XMEMSET(initalCounter, 0, AES_BLOCK_SIZE);
XMEMCPY(initalCounter, iv, ivSz);
initalCounter[AES_BLOCK_SIZE - 1] = 1;
tag = buf;
GHASH(aes, NULL, 0, in, sz, tag, AES_GCM_AUTH_SZ);
wc_AesEncryptDirect(aes, scratch, initalCounter);
xorbuf(tag, scratch, AES_GCM_AUTH_SZ);
}
else {
tag = authTag;
}
/* calls to hardened crypto */
XSecure_AesInitialize(&(aes->xilAes), &(aes->dma), aes->kup,
(word32*)iv, aes->key_init);
XSecure_AesDecryptData(&(aes->xilAes), out, in, sz, tag);
/* account for additional data */
if (authIn != NULL && authInSz > 0) {
GHASH(aes, authIn, authInSz, in, sz, tag, AES_GCM_AUTH_SZ);
wc_AesEncryptDirect(aes, scratch, initalCounter);
xorbuf(tag, scratch, AES_GCM_AUTH_SZ);
if (ConstantCompare(authTag, tag, authTagSz) != 0) {
return AES_GCM_AUTH_E;
}
}
return 0;
}
#endif /* HAVE_AESGCM */
#endif

View file

@ -1,158 +0,0 @@
/* xil-sha3.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_SHA3) && defined(WOLFSSL_XILINX_CRYPT)
#include <wolfssl/wolfcrypt/sha3.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#if !defined(WOLFSSL_NOSHA3_224) || !defined(WOLFSSL_NOSHA3_256) \
|| !defined(WOLFSSL_NOSHA3_512)
#error sizes of SHA3 other than 384 are not supported
#endif
/* Initialize hardware for SHA3 operations
*
* sha SHA3 structure to initialize
* heap memory heap hint to use
* devId used for async operations (currently not supported here)
*/
int wc_InitSha3_384(wc_Sha3* sha, void* heap, int devId)
{
XCsuDma_Config* con;
(void)heap;
(void)devId;
if (sha == NULL) {
return BAD_FUNC_ARG;
}
if ((con = XCsuDma_LookupConfig(0)) == NULL) {
WOLFSSL_MSG("Unable to look up configure for SHA3");
return BAD_STATE_E;
}
/* XST_SUCCESS is success macro from Xilinx header */
if (XCsuDma_CfgInitialize(&(sha->dma), con, con->BaseAddress) !=
XST_SUCCESS) {
WOLFSSL_MSG("Unable to initialize CsuDma");
return BAD_STATE_E;
}
XSecure_Sha3Initialize(&(sha->hw), &(sha->dma));
XSecure_Sha3Start(&(sha->hw));
return 0;
}
/* Update SHA3 state
*
* sha SHA3 structure to update
* data message to update SHA3 state with
* len length of data buffer
*/
int wc_Sha3_384_Update(wc_Sha3* sha, const byte* data, word32 len)
{
if (sha == NULL || (data == NULL && len > 0)) {
return BAD_FUNC_ARG;
}
XSecure_Sha3Update(&(sha->hw), (byte*)data, len);
return 0;
}
/* Finalize SHA3 state and get digest
*
* sha SHA3 structure to get hash
* out digest out, expected to be large enough to hold SHA3 digest
*/
int wc_Sha3_384_Final(wc_Sha3* sha, byte* out)
{
if (sha == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
XSecure_Sha3Finish(&(sha->hw), out);
return wc_InitSha3_384(sha, NULL, INVALID_DEVID);
}
/* Free SHA3 structure
*
* sha SHA3 structure to free
*/
void wc_Sha3_384_Free(wc_Sha3* sha)
{
(void)sha;
/* nothing to free yet */
}
/* Get SHA3 digest without finalize SHA3 state
*
* sha SHA3 structure to get hash
* out digest out, expected to be large enough to hold SHA3 digest
*/
int wc_Sha3_384_GetHash(wc_Sha3* sha, byte* out)
{
wc_Sha3 s;
if (sha == NULL || out == NULL) {
return BAD_FUNC_ARG;
}
if (wc_Sha3_384_Copy(sha, &s) != 0) {
WOLFSSL_MSG("Unable to copy SHA3 structure");
return MEMORY_E;
}
return wc_Sha3_384_Final(&s, out);
}
/* Get copy of SHA3 structure
*
* src SHA3 structure to make copy of
* dst [out]structure to hold copy
*/
int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst)
{
if (src == NULL || dst== NULL) {
return BAD_FUNC_ARG;
}
XMEMCPY((byte*)dst, (byte*)src, sizeof(wc_Sha3));
return 0;
}
#endif

View file

@ -1,60 +0,0 @@
# wolfCrypt Test
Tool for performing cryptographic algorithm testing.
## Example Output
Run on Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz.
```sh
./configure --enable-intelasm --enable-aesni --enable-sp --enable-sp-asm && make
./wolfcrypt/test/testwolfcrypt
------------------------------------------------------------------------------
wolfSSL version 4.0.0
------------------------------------------------------------------------------
error test passed!
MEMORY test passed!
base64 test passed!
asn test passed!
MD5 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!
HMAC-SHA3 test passed!
GMAC test passed!
Chacha test passed!
POLY1305 test passed!
ChaCha20-Poly1305 AEAD test passed!
AES test passed!
AES192 test passed!
AES256 test passed!
AES-GCM test passed!
RANDOM test passed!
RSA test passed!
DH test passed!
ECC test passed!
logging test passed!
mutex test passed!
memcb test passed!
Test complete
```
## Windows Visual Studio
For building wolfCrypt test project in Visual Studio open the `test.sln`. For newer Visual Studio version it may prompt for a one-way upgrade. Then you may have to right-click on the solution and choose `Retarget solution` to update the project files for your Visual Studio version.
If you see an error about `rc.exe` then you'll need to update the "Target Platform Version". You can do this by right-clicking on the test project -> General -> "Target Platform Version" and changing to 8.1 (needs to match the wolfssl library project).
This solution includes the wolfSSL library project at `<wolfssl-root>wolfssl.vcxproj` and will compile the library, then the test project.

View file

@ -1,9 +0,0 @@
AM_CFLAGS=-I m4
#add in wolfssl directory
AM_CPPFLAGS+=-I$(abs_srcdir)/../../ -I$(srcdir)/include/
lib_LTLIBRARIES = lib/libusercrypto.la
lib_libusercrypto_la_CPPFLAGS = $(AM_CPPFLAGS)
lib_libusercrypto_la_LDFLAGS = $(AM_LDFLAGS)
lib_libusercrypto_la_SOURCES = src/rsa.c
include_HEADERS = include/user_rsa.h

View file

@ -1,78 +0,0 @@
/*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/*
Created to use intel's IPP see their license for linking to intel's IPP library
*/
##BUILDING ON 64BIT MAC OSX
Tested and developed on MAC OSX linking to IPP v9.0
for me exporting the IPP library was needed. As an example it was
export DYLD_LIBRARY_PATH="/opt/intel/ipp/lib"
first go to the root wolfssl dir and run ./autogen.sh && ./configure it with desired settings then make. This is to set up the define options and wolfssl library for the user crypto to link to.
Then go to the wolfssl/user-crypto directory and run ./autogen.sh && ./configure then make make install this creates a usercrypto library to use
Finally go back to the root wolfssl directory and follow these build instructions
building wolfSSL add CPPFLAGS=-I/opt/intel/ipp/include for finding the IPP include files
An example build would be
./configure --with-user-crypto CPPFLAGS=-I/opt/intel/ipp/include --enable-lighty
##BUILDING IN 32BIT UBUNTU
Tested on UBUNTU 32 bit linking to IPP v9.0
for me exporting the IPP library. As an example it was
export LD_LIBRARY_PATH="/opt/intel/ipp/lib/ia32_lin/:$LD_LIBRARY_PATH"
first go to the root wolfssl dir and configure it with desired settings and make install. This is to set up the define options and wolfssl library for the user crypto to link to.
For me on Ubuntu the IPP libraries had been installed into /opt/intel/ipp/lib/ia32_lin/ so the ./configure LDFLAGS=-L/opt/intel/ipp/lib/ia32_lin was needed to be looking at that directory.
Run make && make install from the directory wolfssl_root/wolfssl/user-crypto/ this creates a usercrypto library to use
Finally go back to the root wolfssl directory and follow these build instructions
building wolfSSL add CPPFLAGS=-I/opt/intel/ipp/include for finding the IPP include files
./configure --with-user-crypto=root_wolfssl/wolfssl/user-crypto CPPFLAGS=-I/opt/intel/ipp/include (plus any desired additional flags)
##THINGS TO CHECK FOR IF NOT ABLE TO LINK WITH USERCRYPTO LIB
Check that the path has been exported for the IPP library. If usercrypto is unable to use the function to init an RSA key then the link to it will fail in configure. Check for this by $DYLD_LIBRARY_PATH on mac or $LD_LIBRARY_PATH on ubuntu. If the directory for the Intel IPP libraries are not displayed than use "export DYLD_LIBRARY_PATH=path_to_ipp_libraries:$DYLD_LIBRARY_PATH".
##CREATING OWN RSA CRYPTO PLUGIN
It is required to have a header file named user_rsa.h. This is what is looked for by wolfssl/wolfcrypt/rsa.h and should contain the user defined rsa key struct.
It is required to have a library called usercrypto. This is linked to when configuring wolfSSL with the option --with-user-crypto
It is required when compiled with RSA cert generation to have key struct elements named n and e containing the corresponding big numbers. And the three helper functions to work with the big numbers. These functions are called by wolfcrypt/src/asn.c when working with certificates.
To view the needed functions look at wolfssl/wolfcrypt/rsa.h they will be extern functions surrounded by HAVE_USER_RSA define.
Cert Generation for other sign and verify such as ECC are not yet supported.
When building with openssl compatibility layer extra developent needs to be done, having the two functions SetRsaExernal and SetRsaInternal
wolfSSL does not take responsibility for the strength of security of third party cryptography libraries plugged in by the user.

View file

@ -1,23 +0,0 @@
#!/bin/sh
#
# Create configure and makefile stuff...
#
# Git hooks should come before autoreconf.
if test -d .git; then
if ! test -d .git/hooks; then
mkdir .git/hooks
fi
ln -s -f ../../pre-commit.sh .git/hooks/pre-commit
ln -s -f ../../pre-push.sh .git/hooks/pre-push
fi
# If this is a source checkout then call autoreconf with error as well
if test -d .git; then
WARNINGS="all,error"
else
WARNINGS="all"
fi
autoreconf --install --force --verbose

View file

@ -1,44 +0,0 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.63])
AC_INIT([usercypto], [0.1], [])
AC_CONFIG_SRCDIR([src/rsa.c])
AM_INIT_AUTOMAKE([1.11 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects no-define color-tests])
LT_PREREQ([2.2])
LT_INIT([disable-static])
LT_LANG([C++])
LT_LANG([C])
# Checks for programs.
AC_PROG_CC
AC_CONFIG_MACRO_DIR([m4])
# Checks for libraries.
AM_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -L/opt/intel/ipp/lib -lippcp -lippcore"
# Path to find wolfssl/options and other includes
AM_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I../../ -I/opt/intel/ipp/include"
AC_CHECK_LIB([ippcore], [ippGetStatusString], [], [AC_MSG_ERROR([ippcore library needed ./configure LDFLAGS=/path/to/ipp/lib])])
AC_CHECK_LIB([ippcp], [ippsRSA_InitPublicKey], [], [AC_MSG_ERROR([ippcp library needed ./configure LDFLAGS=/path/to/ipp/lib])])
# check headers
AC_CHECK_HEADER([ippcp.h], [], [AC_MSG_ERROR([ippcp.h not found ./configure CPPFLAGS=-I/ipp/headers])])
AC_CHECK_HEADER([ipp.h], [], [AC_MSG_ERROR([ipp.h not found ./configure CPPFLAGS=-I/ipp/headers])])
LDFLAGS=$AM_LDFLAGS
CPPFLAGS=$AM_CPPFLAGS
AM_LDFLAGS="-L/opt/intel/ipp/lib -lippcp -lippcore"
AM_CPPFLAGS="-I/opt/intel/ipp/include"
AC_SUBST([AM_CPPFLAGS])
AC_SUBST([AM_LDFLAGS])
AC_C_INLINE
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View file

@ -1,13 +0,0 @@
if BUILD_FAST_RSA
include_HEADERS += wolfcrypt/user-crypto/include/user_rsa.h
endif
# user crypto plug in example
EXTRA_DIST+= wolfcrypt/user-crypto/configure.ac
EXTRA_DIST+= wolfcrypt/user-crypto/autogen.sh
EXTRA_DIST+= wolfcrypt/user-crypto/include/user_rsa.h
EXTRA_DIST+= wolfcrypt/user-crypto/src/rsa.c
EXTRA_DIST+= wolfcrypt/user-crypto/lib/.gitkeep
EXTRA_DIST+= wolfcrypt/user-crypto/README.txt
EXTRA_DIST+= wolfcrypt/user-crypto/Makefile.am

View file

@ -1,137 +0,0 @@
/* user_rsa.h
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/*
Created to use intel's IPP see their license for linking to intel's IPP library
*/
#ifndef USER_WOLF_CRYPT_RSA_H
#define USER_WOLF_CRYPT_RSA_H
#include <wolfssl/wolfcrypt/settings.h>
#ifndef NO_RSA
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/random.h>
/* intels crypto */
#include <ipp.h>
#include <ippcp.h>
#ifdef __cplusplus
extern "C" {
#endif
/* needed for WOLFSSL_RSA type but use macro guard against redefine */
#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TYPES_DEFINED) \
&& !defined(WOLFSSL_RSA_TYPE_DEFINED)
struct WOLFSSL_RSA;
typedef struct WOLFSSL_RSA WOLFSSL_RSA;
#define WOLFSSL_RSA_TYPE_DEFINED
#endif
enum {
RSA_PUBLIC = 0,
RSA_PRIVATE = 1,
};
/* RSA */
struct RsaKey {
IppsBigNumState* n;
IppsBigNumState* e;
IppsBigNumState* dipp;
IppsBigNumState* pipp;
IppsBigNumState* qipp;
IppsBigNumState* dPipp;
IppsBigNumState* dQipp;
IppsBigNumState* uipp;
int nSz, eSz, dSz;
IppsRSAPublicKeyState* pPub;
IppsRSAPrivateKeyState* pPrv;
word32 prvSz; /* size of private key */
word32 sz; /* size of signature */
int type; /* public or private */
void* heap; /* for user memory overrides */
};
#ifndef WC_RSAKEY_TYPE_DEFINED
typedef struct RsaKey RsaKey;
#define WC_RSAKEY_TYPE_DEFINED
#endif
WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*);
WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId);
WOLFSSL_API int wc_FreeRsaKey(RsaKey* key);
WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, WC_RNG* rng);
WOLFSSL_API int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out,
RsaKey* key);
WOLFSSL_API int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key);
WOLFSSL_API int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key, WC_RNG* rng);
WOLFSSL_API int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out,
RsaKey* key);
WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out,
word32 outLen, RsaKey* key);
WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key);
WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx,
RsaKey*, word32);
WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx,
word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz);
WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx,
RsaKey*, word32);
WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz,
const byte* e, word32 eSz, RsaKey* key);
WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen);
WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen);
#ifdef WOLFSSL_KEY_GEN
WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng);
#endif
WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*,
word32*);
WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng);
#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)
/* abstracted BN operations with RSA key */
WOLFSSL_API int wc_Rsa_leading_bit(void* BN);
WOLFSSL_API int wc_Rsa_unsigned_bin_size(void* BN);
/* return MP_OKAY on success */
WOLFSSL_API int wc_Rsa_to_unsigned_bin(void* BN, byte* in, int inLen);
#endif
#ifdef OPENSSL_EXTRA /* abstracted functions to deal with rsa key */
WOLFSSL_API int SetRsaExternal(WOLFSSL_RSA* rsa);
WOLFSSL_API int SetRsaInternal(WOLFSSL_RSA* rsa);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* NO_RSA */
#endif /* USER_WOLF_CRYPT_RSA_H */

File diff suppressed because it is too large Load diff