Add the fast crypto function in supplicant

optimize the speed when do wifi connect
This commit is contained in:
Deng Xin
2017-08-01 22:29:16 +08:00
parent 1c4f7f2081
commit 57bc38d867
25 changed files with 1673 additions and 26 deletions

View File

@@ -0,0 +1,78 @@
// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
#include "crypto/includes.h"
#include "crypto/common.h"
#include "crypto/aes.h"
#include "crypto/aes_wrap.h"
#include "mbedtls/aes.h"
/**
* fast_aes_128_cbc_encrypt - AES-128 CBC encryption
* @key: Encryption key
* @iv: Encryption IV for CBC mode (16 bytes)
* @data: Data to encrypt in-place
* @data_len: Length of data in bytes (must be divisible by 16)
* Returns: 0 on success, -1 on failure
*/
int
fast_aes_128_cbc_encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, size_t data_len)
{
int ret = 0;
mbedtls_aes_context ctx;
uint8_t cbc[AES_BLOCK_SIZE];
mbedtls_aes_init(&ctx);
ret = mbedtls_aes_setkey_enc(&ctx, key, 128);
if(ret < 0) {
mbedtls_aes_free(&ctx);
return ret;
}
os_memcpy(cbc, iv, AES_BLOCK_SIZE);
ret = mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, data_len, cbc, data, data);
mbedtls_aes_free(&ctx);
return ret;
}
/**
* fast_aes_128_cbc_decrypt - AES-128 CBC decryption
* @key: Decryption key
* @iv: Decryption IV for CBC mode (16 bytes)
* @data: Data to decrypt in-place
* @data_len: Length of data in bytes (must be divisible by 16)
* Returns: 0 on success, -1 on failure
*/
int
fast_aes_128_cbc_decrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, size_t data_len)
{
int ret = 0;
mbedtls_aes_context ctx;
uint8_t cbc[AES_BLOCK_SIZE];
mbedtls_aes_init(&ctx);
ret = mbedtls_aes_setkey_dec(&ctx, key, 128);
if(ret < 0) {
mbedtls_aes_free(&ctx);
return ret;
}
os_memcpy(cbc, iv, AES_BLOCK_SIZE);
ret = mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, data_len, cbc, data, data);
mbedtls_aes_free(&ctx);
return ret;
}

View File

@@ -0,0 +1,81 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "crypto/includes.h"
#include "crypto/common.h"
#include "mbedtls/aes.h"
/**
* fast_aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
* @kek: Key encryption key (KEK)
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
* bytes
* @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
* @plain: Plaintext key, n * 64 bits
* Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
*/
int
fast_aes_unwrap(const uint8_t *kek, int n, const uint8_t *cipher, uint8_t *plain)
{
uint8_t a[8], *r, b[16];
int32_t i, j;
int32_t ret = 0;
mbedtls_aes_context ctx;
/* 1) Initialize variables. */
os_memcpy(a, cipher, 8);
r = plain;
os_memcpy(r, cipher + 8, 8 * n);
mbedtls_aes_init(&ctx);
ret = mbedtls_aes_setkey_dec(&ctx, kek, 128);
if (ret < 0) {
mbedtls_aes_free(&ctx);
return ret;
}
/* 2) Compute intermediate values.
* For j = 5 to 0
* For i = n to 1
* B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
* A = MSB(64, B)
* R[i] = LSB(64, B)
*/
for (j = 5; j >= 0; j--) {
r = plain + (n - 1) * 8;
for (i = n; i >= 1; i--) {
os_memcpy(b, a, 8);
b[7] ^= n * j + i;
os_memcpy(b + 8, r, 8);
mbedtls_aes_decrypt(&ctx, b, b);
os_memcpy(a, b, 8);
os_memcpy(r, b + 8, 8);
r -= 8;
}
}
mbedtls_aes_free(&ctx);
/* 3) Output results.
*
* These are already in @plain due to the location of temporary
* variables. Just verify that the IV matches with the expected value.
*/
for (i = 0; i < 8; i++) {
if (a[i] != 0xa6) {
return -1;
}
}
return 0;
}

View File

@@ -0,0 +1,80 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "crypto/includes.h"
#include "crypto/common.h"
#include "crypto/aes.h"
#include "crypto/aes_wrap.h"
#include "mbedtls/aes.h"
/**
* fast_aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
* @kek: 16-octet Key encryption key (KEK)
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
* bytes
* @plain: Plaintext key to be wrapped, n * 64 bits
* @cipher: Wrapped key, (n + 1) * 64 bits
* Returns: 0 on success, -1 on failure
*/
int fast_aes_wrap(const uint8_t *kek, int n, const uint8_t *plain, uint8_t *cipher)
{
uint8_t *a, *r, b[16];
int32_t i, j;
int32_t ret = 0;
mbedtls_aes_context ctx;
a = cipher;
r = cipher + 8;
/* 1) Initialize variables. */
os_memset(a, 0xa6, 8);
os_memcpy(r, plain, 8 * n);
mbedtls_aes_init(&ctx);
ret = mbedtls_aes_setkey_enc(&ctx, kek, 128);
if (ret < 0) {
mbedtls_aes_free(&ctx);
return ret;
}
/* 2) Calculate intermediate values.
* For j = 0 to 5
* For i=1 to n
* B = AES(K, A | R[i])
* A = MSB(64, B) ^ t where t = (n*j)+i
* R[i] = LSB(64, B)
*/
for (j = 0; j <= 5; j++) {
r = cipher + 8;
for (i = 1; i <= n; i++) {
os_memcpy(b, a, 8);
os_memcpy(b + 8, r, 8);
mbedtls_aes_encrypt(&ctx, b, b);
os_memcpy(a, b, 8);
a[7] ^= n * j + i;
os_memcpy(r, b + 8, 8);
r += 8;
}
}
mbedtls_aes_free(&ctx);
/* 3) Output the results.
*
* These are already in @cipher due to the location of temporary
* variables.
*/
return 0;
}

View File

@@ -0,0 +1,283 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//#include "wpa/includes.h"
//#include "wpa/common.h"
#include "crypto/common.h"
#include "crypto/crypto.h"
#include "crypto/aes.h"
#if defined(CONFIG_DES) || defined(CONFIG_DES3)
#include "crypto/des_i.h"
#endif
#include "mbedtls/aes.h"
struct fast_crypto_cipher {
enum crypto_cipher_alg alg;
union {
struct {
size_t used_bytes;
uint8_t key[16];
size_t keylen;
} rc4;
struct {
uint8_t cbc[32];
mbedtls_aes_context ctx_enc;
mbedtls_aes_context ctx_dec;
} aes;
#ifdef CONFIG_DES3
struct {
struct des3_key_s key;
uint8_t cbc[8];
} des3;
#endif
#ifdef CONFIG_DES
struct {
uint32_t ek[32];
uint32_t dk[32];
uint32_t cbc[8];
} des;
#endif
} u;
};
struct crypto_cipher * fast_crypto_cipher_init(enum crypto_cipher_alg alg,
const uint8_t *iv, const uint8_t *key,
size_t key_len)
{
struct fast_crypto_cipher *ctx;
ctx = (struct fast_crypto_cipher *)os_zalloc(sizeof(*ctx));
if (ctx == NULL) {
return NULL;
}
ctx->alg = alg;
switch (alg) {
case CRYPTO_CIPHER_ALG_RC4:
if (key_len > sizeof(ctx->u.rc4.key)) {
os_free(ctx);
return NULL;
}
ctx->u.rc4.keylen = key_len;
os_memcpy(ctx->u.rc4.key, key, key_len);
break;
case CRYPTO_CIPHER_ALG_AES:
mbedtls_aes_init(&(ctx->u.aes.ctx_enc));
mbedtls_aes_setkey_enc(&(ctx->u.aes.ctx_enc), key, 256);
mbedtls_aes_init(&(ctx->u.aes.ctx_dec));
mbedtls_aes_setkey_dec(&(ctx->u.aes.ctx_dec), key, 256);
os_memcpy(ctx->u.aes.cbc, iv, AES_BLOCK_SIZE);
break;
#ifdef CONFIG_DES3
case CRYPTO_CIPHER_ALG_3DES:
if (key_len != 24) {
os_free(ctx);
return NULL;
}
des3_key_setup(key, &ctx->u.des3.key);
os_memcpy(ctx->u.des3.cbc, iv, 8);
break;
#endif
#ifdef CONFIG_DES
case CRYPTO_CIPHER_ALG_DES:
if (key_len != 8) {
os_free(ctx);
return NULL;
}
des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk);
os_memcpy(ctx->u.des.cbc, iv, 8);
break;
#endif
default:
os_free(ctx);
return NULL;
}
return (struct crypto_cipher *)ctx;
}
int fast_crypto_cipher_encrypt(struct crypto_cipher *ctx, const uint8_t *plain,
uint8_t *crypt, size_t len)
{
size_t i, j, blocks;
struct fast_crypto_cipher *fast_ctx;
fast_ctx = (struct fast_crypto_cipher *)ctx;
switch (fast_ctx->alg) {
case CRYPTO_CIPHER_ALG_RC4:
if (plain != crypt) {
os_memcpy(crypt, plain, len);
}
rc4_skip(fast_ctx->u.rc4.key, fast_ctx->u.rc4.keylen,
fast_ctx->u.rc4.used_bytes, crypt, len);
fast_ctx->u.rc4.used_bytes += len;
break;
case CRYPTO_CIPHER_ALG_AES:
if (len % AES_BLOCK_SIZE) {
return -1;
}
blocks = len / AES_BLOCK_SIZE;
for (i = 0; i < blocks; i++) {
for (j = 0; j < AES_BLOCK_SIZE; j++)
fast_ctx->u.aes.cbc[j] ^= plain[j];
mbedtls_aes_encrypt(&(fast_ctx->u.aes.ctx_enc), fast_ctx->u.aes.cbc, fast_ctx->u.aes.cbc);
os_memcpy(crypt, fast_ctx->u.aes.cbc, AES_BLOCK_SIZE);
plain += AES_BLOCK_SIZE;
crypt += AES_BLOCK_SIZE;
}
break;
#ifdef CONFIG_DES3
case CRYPTO_CIPHER_ALG_3DES:
if (len % 8) {
return -1;
}
blocks = len / 8;
for (i = 0; i < blocks; i++) {
for (j = 0; j < 8; j++)
fast_ctx->u.des3.cbc[j] ^= plain[j];
des3_encrypt(fast_ctx->u.des3.cbc, &fast_ctx->u.des3.key,
fast_ctx->u.des3.cbc);
os_memcpy(crypt, fast_ctx->u.des3.cbc, 8);
plain += 8;
crypt += 8;
}
break;
#endif
#ifdef CONFIG_DES
case CRYPTO_CIPHER_ALG_DES:
if (len % 8) {
return -1;
}
blocks = len / 8;
for (i = 0; i < blocks; i++) {
for (j = 0; j < 8; j++)
fast_ctx->u.des3.cbc[j] ^= plain[j];
des_block_encrypt(fast_ctx->u.des.cbc, fast_ctx->u.des.ek,
fast_ctx->u.des.cbc);
os_memcpy(crypt, fast_ctx->u.des.cbc, 8);
plain += 8;
crypt += 8;
}
break;
#endif
default:
return -1;
}
return 0;
}
int fast_crypto_cipher_decrypt(struct crypto_cipher *ctx, const uint8_t *crypt,
uint8_t *plain, size_t len)
{
size_t i, j, blocks;
uint8_t tmp[32];
struct fast_crypto_cipher *fast_ctx;
fast_ctx = (struct fast_crypto_cipher *)ctx;
switch (fast_ctx->alg) {
case CRYPTO_CIPHER_ALG_RC4:
if (plain != crypt) {
os_memcpy(plain, crypt, len);
}
rc4_skip(fast_ctx->u.rc4.key, fast_ctx->u.rc4.keylen,
fast_ctx->u.rc4.used_bytes, plain, len);
fast_ctx->u.rc4.used_bytes += len;
break;
case CRYPTO_CIPHER_ALG_AES:
if (len % AES_BLOCK_SIZE) {
return -1;
}
blocks = len / AES_BLOCK_SIZE;
for (i = 0; i < blocks; i++) {
os_memcpy(tmp, crypt, AES_BLOCK_SIZE);
mbedtls_aes_decrypt(&(fast_ctx->u.aes.ctx_dec), crypt, plain);
for (j = 0; j < AES_BLOCK_SIZE; j++)
plain[j] ^= fast_ctx->u.aes.cbc[j];
os_memcpy(fast_ctx->u.aes.cbc, tmp, AES_BLOCK_SIZE);
plain += AES_BLOCK_SIZE;
crypt += AES_BLOCK_SIZE;
}
break;
#ifdef CONFIG_DES3
case CRYPTO_CIPHER_ALG_3DES:
if (len % 8) {
return -1;
}
blocks = len / 8;
for (i = 0; i < blocks; i++) {
os_memcpy(tmp, crypt, 8);
des3_decrypt(crypt, &fast_ctx->u.des3.key, plain);
for (j = 0; j < 8; j++) {
plain[j] ^= fast_ctx->u.des3.cbc[j];
}
os_memcpy(fast_ctx->u.des3.cbc, tmp, 8);
plain += 8;
crypt += 8;
}
break;
#endif
#ifdef CONFIG_DES
case CRYPTO_CIPHER_ALG_DES:
if (len % 8) {
return -1;
}
blocks = len / 8;
for (i = 0; i < blocks; i++) {
os_memcpy(tmp, crypt, 8);
des_block_decrypt(crypt, fast_ctx->u.des.dk, plain);
for (j = 0; j < 8; j++) {
plain[j] ^= fast_ctx->u.des.cbc[j];
}
os_memcpy(fast_ctx->u.des.cbc, tmp, 8);
plain += 8;
crypt += 8;
}
break;
#endif
default:
return -1;
}
return 0;
}
void fast_crypto_cipher_deinit(struct crypto_cipher *ctx)
{
struct fast_crypto_cipher *fast_ctx;
fast_ctx = (struct fast_crypto_cipher *)ctx;
switch (fast_ctx->alg) {
case CRYPTO_CIPHER_ALG_AES:
mbedtls_aes_free(&(fast_ctx->u.aes.ctx_enc));
mbedtls_aes_free(&(fast_ctx->u.aes.ctx_dec));
break;
#ifdef CONFIG_DES3
case CRYPTO_CIPHER_ALG_3DES:
break;
#endif
default:
break;
}
os_free(ctx);
}

View File

@@ -0,0 +1,59 @@
// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "crypto/includes.h"
#include "crypto/common.h"
#include "crypto/crypto.h"
#include "mbedtls/bignum.h"
int
fast_crypto_mod_exp(const uint8_t *base, size_t base_len,
const uint8_t *power, size_t power_len,
const uint8_t *modulus, size_t modulus_len,
uint8_t *result, size_t *result_len)
{
mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result, bn_rinv;
int32_t ret = 0;
mbedtls_mpi_init(&bn_base);
mbedtls_mpi_init(&bn_exp);
mbedtls_mpi_init(&bn_modulus);
mbedtls_mpi_init(&bn_result);
mbedtls_mpi_init(&bn_rinv);
mbedtls_mpi_read_binary(&bn_base, base, base_len);
mbedtls_mpi_read_binary(&bn_exp, power, power_len);
mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len);
ret = mbedtls_mpi_exp_mod(&bn_result, &bn_base, &bn_exp, &bn_modulus, &bn_rinv);
if (ret < 0) {
mbedtls_mpi_free(&bn_base);
mbedtls_mpi_free(&bn_exp);
mbedtls_mpi_free(&bn_modulus);
mbedtls_mpi_free(&bn_result);
mbedtls_mpi_free(&bn_rinv);
return ret;
}
ret = mbedtls_mpi_write_binary(&bn_result, result, *result_len);
mbedtls_mpi_free(&bn_base);
mbedtls_mpi_free(&bn_exp);
mbedtls_mpi_free(&bn_modulus);
mbedtls_mpi_free(&bn_result);
mbedtls_mpi_free(&bn_rinv);
return ret;
}

View File

@@ -0,0 +1,282 @@
/*
* Crypto wrapper for internal crypto implementation
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
*
* Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "crypto/includes.h"
#include "crypto/common.h"
#include "crypto/crypto.h"
#include "crypto/sha1_i.h"
#include "crypto/md5_i.h"
#include "mbedtls/sha256.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
struct fast_crypto_hash {
enum crypto_hash_alg alg;
union {
struct MD5Context md5;
struct SHA1Context sha1;
#ifdef CONFIG_SHA256
mbedtls_sha256_context sha256;
#endif /* CONFIG_SHA256 */
} u;
u8 key[64];
size_t key_len;
};
struct crypto_hash * fast_crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
size_t key_len)
{
struct fast_crypto_hash *ctx;
u8 k_pad[64];
u8 tk[32];
size_t i;
ctx = (struct fast_crypto_hash *)os_zalloc(sizeof(*ctx));
if (ctx == NULL)
return NULL;
ctx->alg = alg;
switch (alg) {
case CRYPTO_HASH_ALG_MD5:
MD5Init(&ctx->u.md5);
break;
case CRYPTO_HASH_ALG_SHA1:
SHA1Init(&ctx->u.sha1);
break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_SHA256:
mbedtls_sha256_init(&ctx->u.sha256);
mbedtls_sha256_starts(&ctx->u.sha256, 0);
break;
#endif /* CONFIG_SHA256 */
case CRYPTO_HASH_ALG_HMAC_MD5:
if (key_len > sizeof(k_pad)) {
MD5Init(&ctx->u.md5);
MD5Update(&ctx->u.md5, key, key_len);
MD5Final(tk, &ctx->u.md5);
key = tk;
key_len = 16;
}
os_memcpy(ctx->key, key, key_len);
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
if (key_len < sizeof(k_pad))
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
MD5Init(&ctx->u.md5);
MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
break;
case CRYPTO_HASH_ALG_HMAC_SHA1:
if (key_len > sizeof(k_pad)) {
SHA1Init(&ctx->u.sha1);
SHA1Update(&ctx->u.sha1, key, key_len);
SHA1Final(tk, &ctx->u.sha1);
key = tk;
key_len = 20;
}
os_memcpy(ctx->key, key, key_len);
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
if (key_len < sizeof(k_pad))
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
SHA1Init(&ctx->u.sha1);
SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_HMAC_SHA256:
if (key_len > sizeof(k_pad)) {
mbedtls_sha256_init(&ctx->u.sha256);
mbedtls_sha256_starts(&ctx->u.sha256, 0);
mbedtls_sha256_update(&ctx->u.sha256, key, key_len);
mbedtls_sha256_finish(&ctx->u.sha256, tk);
mbedtls_sha256_free(&ctx->u.sha256);
key = tk;
key_len = 32;
}
os_memcpy(ctx->key, key, key_len);
ctx->key_len = key_len;
os_memcpy(k_pad, key, key_len);
if (key_len < sizeof(k_pad))
os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x36;
mbedtls_sha256_init(&ctx->u.sha256);
mbedtls_sha256_starts(&ctx->u.sha256, 0);
mbedtls_sha256_update(&ctx->u.sha256, k_pad, sizeof(k_pad));
break;
#endif /* CONFIG_SHA256 */
default:
os_free(ctx);
return NULL;
}
return (struct crypto_hash *)ctx;
}
void fast_crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
{
struct fast_crypto_hash *fast_ctx;
fast_ctx = (struct fast_crypto_hash *)ctx;
if (fast_ctx == NULL)
return;
switch (fast_ctx->alg) {
case CRYPTO_HASH_ALG_MD5:
case CRYPTO_HASH_ALG_HMAC_MD5:
MD5Update(&fast_ctx->u.md5, data, len);
break;
case CRYPTO_HASH_ALG_SHA1:
case CRYPTO_HASH_ALG_HMAC_SHA1:
SHA1Update(&fast_ctx->u.sha1, data, len);
break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_SHA256:
case CRYPTO_HASH_ALG_HMAC_SHA256:
mbedtls_sha256_update(&fast_ctx->u.sha256, data, len);
break;
#endif /* CONFIG_SHA256 */
default:
break;
}
}
int fast_crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
{
u8 k_pad[64];
size_t i;
struct fast_crypto_hash *fast_ctx;
if (ctx == NULL)
return -2;
fast_ctx = (struct fast_crypto_hash *)ctx;
if (mac == NULL || len == NULL) {
os_free(fast_ctx);
return 0;
}
switch (fast_ctx->alg) {
case CRYPTO_HASH_ALG_MD5:
if (*len < 16) {
*len = 16;
os_free(fast_ctx);
return -1;
}
*len = 16;
MD5Final(mac, &fast_ctx->u.md5);
break;
case CRYPTO_HASH_ALG_SHA1:
if (*len < 20) {
*len = 20;
os_free(fast_ctx);
return -1;
}
*len = 20;
SHA1Final(mac, &fast_ctx->u.sha1);
break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_SHA256:
if (*len < 32) {
*len = 32;
os_free(fast_ctx);
return -1;
}
*len = 32;
mbedtls_sha256_finish(&fast_ctx->u.sha256, mac);
mbedtls_sha256_free(&fast_ctx->u.sha256);
break;
#endif /* CONFIG_SHA256 */
case CRYPTO_HASH_ALG_HMAC_MD5:
if (*len < 16) {
*len = 16;
os_free(fast_ctx);
return -1;
}
*len = 16;
MD5Final(mac, &fast_ctx->u.md5);
os_memcpy(k_pad, fast_ctx->key, fast_ctx->key_len);
os_memset(k_pad + fast_ctx->key_len, 0,
sizeof(k_pad) - fast_ctx->key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x5c;
MD5Init(&fast_ctx->u.md5);
MD5Update(&fast_ctx->u.md5, k_pad, sizeof(k_pad));
MD5Update(&fast_ctx->u.md5, mac, 16);
MD5Final(mac, &fast_ctx->u.md5);
break;
case CRYPTO_HASH_ALG_HMAC_SHA1:
if (*len < 20) {
*len = 20;
os_free(ctx);
return -1;
}
*len = 20;
SHA1Final(mac, &fast_ctx->u.sha1);
os_memcpy(k_pad, fast_ctx->key, fast_ctx->key_len);
os_memset(k_pad + fast_ctx->key_len, 0,
sizeof(k_pad) - fast_ctx->key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x5c;
SHA1Init(&fast_ctx->u.sha1);
SHA1Update(&fast_ctx->u.sha1, k_pad, sizeof(k_pad));
SHA1Update(&fast_ctx->u.sha1, mac, 20);
SHA1Final(mac, &fast_ctx->u.sha1);
break;
#ifdef CONFIG_SHA256
case CRYPTO_HASH_ALG_HMAC_SHA256:
if (*len < 32) {
*len = 32;
os_free(fast_ctx);
return -1;
}
*len = 32;
mbedtls_sha256_finish(&fast_ctx->u.sha256, mac);
mbedtls_sha256_free(&fast_ctx->u.sha256);
os_memcpy(k_pad, fast_ctx->key, fast_ctx->key_len);
os_memset(k_pad + fast_ctx->key_len, 0,
sizeof(k_pad) - fast_ctx->key_len);
for (i = 0; i < sizeof(k_pad); i++)
k_pad[i] ^= 0x5c;
mbedtls_sha256_init(&fast_ctx->u.sha256);
mbedtls_sha256_starts(&fast_ctx->u.sha256, 0);
mbedtls_sha256_update(&fast_ctx->u.sha256, k_pad, sizeof(k_pad));
mbedtls_sha256_update(&fast_ctx->u.sha256, mac, 32);
mbedtls_sha256_finish(&fast_ctx->u.sha256, mac);
mbedtls_sha256_free(&fast_ctx->u.sha256);
break;
#endif /* CONFIG_SHA256 */
default:
os_free(fast_ctx);
return -1;
}
os_free(fast_ctx);
return 0;
}

View File

@@ -0,0 +1,48 @@
// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "crypto/includes.h"
#include "crypto/common.h"
#include "mbedtls/sha256.h"
/**
* fast_sha256_vector - SHA256 hash for data vector
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for the hash
* Returns: 0 on success, -1 of failure
*/
int
fast_sha256_vector(size_t num_elem, const uint8_t *addr[], const size_t *len,
uint8_t *mac)
{
mbedtls_sha256_context ctx;
mbedtls_sha256_init(&ctx);
mbedtls_sha256_starts(&ctx, 0);
for(size_t index = 0; index < num_elem; index++) {
mbedtls_sha256_update(&ctx, addr[index], len[index]);
}
mbedtls_sha256_finish(&ctx, mac);
mbedtls_sha256_free(&ctx);
return 0;
}

View File

@@ -0,0 +1,165 @@
/*
* SHA-256 hash implementation and interface functions
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
* Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include "crypto/includes.h"
#include "crypto/common.h"
#include "crypto/sha256.h"
#include "crypto/crypto.h"
/**
* fast_hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
* @key: Key for HMAC operations
* @key_len: Length of the key in bytes
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for the hash (32 bytes)
*/
void
fast_hmac_sha256_vector(const uint8_t *key, size_t key_len, size_t num_elem,
const uint8_t *addr[], const size_t *len, uint8_t *mac)
{
uint8_t k_pad[64]; /* padding - key XORd with ipad/opad */
uint8_t tk[32];
const uint8_t *_addr[6];
size_t _len[6], i;
if (num_elem > 5) {
/*
* Fixed limit on the number of fragments to avoid having to
* allocate memory (which could fail).
*/
return;
}
/* if key is longer than 64 bytes reset it to key = SHA256(key) */
if (key_len > 64) {
fast_sha256_vector(1, &key, &key_len, tk);
key = tk;
key_len = 32;
}
/* the HMAC_SHA256 transform looks like:
*
* SHA256(K XOR opad, SHA256(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/* start out by storing key in ipad */
os_memset(k_pad, 0, sizeof(k_pad));
os_memcpy(k_pad, key, key_len);
/* XOR key with ipad values */
for (i = 0; i < 64; i++) {
k_pad[i] ^= 0x36;
}
/* perform inner SHA256 */
_addr[0] = k_pad;
_len[0] = 64;
for (i = 0; i < num_elem; i++) {
_addr[i + 1] = addr[i];
_len[i + 1] = len[i];
}
fast_sha256_vector(1 + num_elem, _addr, _len, mac);
os_memset(k_pad, 0, sizeof(k_pad));
os_memcpy(k_pad, key, key_len);
/* XOR key with opad values */
for (i = 0; i < 64; i++) {
k_pad[i] ^= 0x5c;
}
/* perform outer SHA256 */
_addr[0] = k_pad;
_len[0] = 64;
_addr[1] = mac;
_len[1] = SHA256_MAC_LEN;
fast_sha256_vector(2, _addr, _len, mac);
}
/**
* fast_hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
* @key: Key for HMAC operations
* @key_len: Length of the key in bytes
* @data: Pointers to the data area
* @data_len: Length of the data area
* @mac: Buffer for the hash (20 bytes)
*/
void
fast_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *data,
size_t data_len, uint8_t *mac)
{
fast_hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
}
/**
* fast_sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
* @key: Key for PRF
* @key_len: Length of the key in bytes
* @label: A unique label for each purpose of the PRF
* @data: Extra data to bind into the key
* @data_len: Length of the data
* @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bytes of key to generate
*
* This function is used to derive new, cryptographically separate keys from a
* given key.
*/
void
fast_sha256_prf(const uint8_t *key, size_t key_len, const char *label,
const uint8_t *data, size_t data_len, uint8_t *buf, size_t buf_len)
{
uint16_t counter = 1;
size_t pos, plen;
uint8_t hash[SHA256_MAC_LEN];
const uint8_t *addr[4];
size_t len[4];
uint8_t counter_le[2], length_le[2];
addr[0] = counter_le;
len[0] = 2;
addr[1] = (uint8_t *) label;
len[1] = os_strlen(label);
addr[2] = data;
len[2] = data_len;
addr[3] = length_le;
len[3] = sizeof(length_le);
WPA_PUT_LE16(length_le, buf_len * 8);
pos = 0;
while (pos < buf_len) {
plen = buf_len - pos;
WPA_PUT_LE16(counter_le, counter);
if (plen >= SHA256_MAC_LEN) {
fast_hmac_sha256_vector(key, key_len, 4, addr, len,
&buf[pos]);
pos += SHA256_MAC_LEN;
} else {
fast_hmac_sha256_vector(key, key_len, 4, addr, len, hash);
os_memcpy(&buf[pos], hash, plen);
break;
}
counter++;
}
}