mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-24 01:25:36 +00:00
wpa_supplicant: Port dpp feature from supplicant
Add files required for DPP feature from upstream. These file expose the functionality to create DPP packets. Ported crypto layer from openssl to mbedtls. Interfacing to use these API will be added in seperate commit
This commit is contained in:
208
components/wpa_supplicant/src/crypto/aes-siv.c
Normal file
208
components/wpa_supplicant/src/crypto/aes-siv.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* AES SIV (RFC 5297)
|
||||
* Copyright (c) 2013 Cozybit, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
|
||||
#include "crypto/aes.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "crypto/aes_siv.h"
|
||||
|
||||
|
||||
static const u8 zero[AES_BLOCK_SIZE];
|
||||
|
||||
|
||||
static void dbl(u8 *pad)
|
||||
{
|
||||
int i, carry;
|
||||
|
||||
carry = pad[0] & 0x80;
|
||||
for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
|
||||
pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
|
||||
pad[AES_BLOCK_SIZE - 1] <<= 1;
|
||||
if (carry)
|
||||
pad[AES_BLOCK_SIZE - 1] ^= 0x87;
|
||||
}
|
||||
|
||||
|
||||
static void xor(u8 *a, const u8 *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
*a++ ^= *b++;
|
||||
}
|
||||
|
||||
|
||||
static void xorend(u8 *a, int alen, const u8 *b, int blen)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (alen < blen)
|
||||
return;
|
||||
|
||||
for (i = 0; i < blen; i++)
|
||||
a[alen - blen + i] ^= b[i];
|
||||
}
|
||||
|
||||
|
||||
static void pad_block(u8 *pad, const u8 *addr, size_t len)
|
||||
{
|
||||
os_memset(pad, 0, AES_BLOCK_SIZE);
|
||||
os_memcpy(pad, addr, len);
|
||||
|
||||
if (len < AES_BLOCK_SIZE)
|
||||
pad[len] = 0x80;
|
||||
}
|
||||
|
||||
|
||||
static int aes_s2v(const u8 *key, size_t key_len,
|
||||
size_t num_elem, const u8 *addr[], size_t *len, u8 *mac)
|
||||
{
|
||||
u8 tmp[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
|
||||
u8 *buf = NULL;
|
||||
int ret;
|
||||
size_t i;
|
||||
const u8 *data[1];
|
||||
size_t data_len[1];
|
||||
|
||||
if (!num_elem) {
|
||||
os_memcpy(tmp, zero, sizeof(zero));
|
||||
tmp[AES_BLOCK_SIZE - 1] = 1;
|
||||
data[0] = tmp;
|
||||
data_len[0] = sizeof(tmp);
|
||||
return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
|
||||
}
|
||||
|
||||
data[0] = zero;
|
||||
data_len[0] = sizeof(zero);
|
||||
ret = omac1_aes_vector(key, key_len, 1, data, data_len, tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < num_elem - 1; i++) {
|
||||
ret = omac1_aes_vector(key, key_len, 1, &addr[i], &len[i],
|
||||
tmp2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dbl(tmp);
|
||||
xor(tmp, tmp2);
|
||||
}
|
||||
if (len[i] >= AES_BLOCK_SIZE) {
|
||||
buf = os_memdup(addr[i], len[i]);
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
|
||||
data[0] = buf;
|
||||
ret = omac1_aes_vector(key, key_len, 1, data, &len[i], mac);
|
||||
bin_clear_free(buf, len[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dbl(tmp);
|
||||
pad_block(tmp2, addr[i], len[i]);
|
||||
xor(tmp, tmp2);
|
||||
|
||||
data[0] = tmp;
|
||||
data_len[0] = sizeof(tmp);
|
||||
return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
|
||||
}
|
||||
|
||||
|
||||
int aes_siv_encrypt(const u8 *key, size_t key_len,
|
||||
const u8 *pw, size_t pwlen,
|
||||
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *out)
|
||||
{
|
||||
const u8 *_addr[6];
|
||||
size_t _len[6];
|
||||
const u8 *k1, *k2;
|
||||
u8 v[AES_BLOCK_SIZE];
|
||||
size_t i;
|
||||
u8 *iv, *crypt_pw;
|
||||
|
||||
if (num_elem > ARRAY_SIZE(_addr) - 1 ||
|
||||
(key_len != 32 && key_len != 48 && key_len != 64))
|
||||
return -1;
|
||||
|
||||
key_len /= 2;
|
||||
k1 = key;
|
||||
k2 = key + key_len;
|
||||
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i] = addr[i];
|
||||
_len[i] = len[i];
|
||||
}
|
||||
_addr[num_elem] = pw;
|
||||
_len[num_elem] = pwlen;
|
||||
|
||||
if (aes_s2v(k1, key_len, num_elem + 1, _addr, _len, v))
|
||||
return -1;
|
||||
|
||||
iv = out;
|
||||
crypt_pw = out + AES_BLOCK_SIZE;
|
||||
|
||||
os_memcpy(iv, v, AES_BLOCK_SIZE);
|
||||
os_memcpy(crypt_pw, pw, pwlen);
|
||||
|
||||
/* zero out 63rd and 31st bits of ctr (from right) */
|
||||
v[8] &= 0x7f;
|
||||
v[12] &= 0x7f;
|
||||
return aes_ctr_encrypt(k2, key_len, v, crypt_pw, pwlen);
|
||||
}
|
||||
|
||||
|
||||
int aes_siv_decrypt(const u8 *key, size_t key_len,
|
||||
const u8 *iv_crypt, size_t iv_c_len,
|
||||
size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *out)
|
||||
{
|
||||
const u8 *_addr[6];
|
||||
size_t _len[6];
|
||||
const u8 *k1, *k2;
|
||||
size_t crypt_len;
|
||||
size_t i;
|
||||
int ret;
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
u8 check[AES_BLOCK_SIZE];
|
||||
|
||||
if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1 ||
|
||||
(key_len != 32 && key_len != 48 && key_len != 64))
|
||||
return -1;
|
||||
crypt_len = iv_c_len - AES_BLOCK_SIZE;
|
||||
key_len /= 2;
|
||||
k1 = key;
|
||||
k2 = key + key_len;
|
||||
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i] = addr[i];
|
||||
_len[i] = len[i];
|
||||
}
|
||||
_addr[num_elem] = out;
|
||||
_len[num_elem] = crypt_len;
|
||||
|
||||
os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
|
||||
os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len);
|
||||
|
||||
iv[8] &= 0x7f;
|
||||
iv[12] &= 0x7f;
|
||||
|
||||
ret = aes_ctr_encrypt(k2, key_len, iv, out, crypt_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = aes_s2v(k1, key_len, num_elem + 1, _addr, _len, check);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
Reference in New Issue
Block a user