aboutsummaryrefslogtreecommitdiffstats
path: root/wlantest
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2012-09-08 20:40:06 (GMT)
committerJouni Malinen <j@w1.fi>2012-09-08 20:40:06 (GMT)
commitbe87d3c34531a062335afa21bfec72876d5585cf (patch)
tree960baa9347c94419dbeab22b7c07a1425d47666b /wlantest
parentb4a5fcb28676e0df8bce63de9f73c61932b282ca (diff)
downloadhostap-be87d3c34531a062335afa21bfec72876d5585cf.zip
hostap-be87d3c34531a062335afa21bfec72876d5585cf.tar.gz
hostap-be87d3c34531a062335afa21bfec72876d5585cf.tar.bz2
wlantest: Allow GHASH update calls to avoid extra allocation
There is no need to allocate a temporary buffer and build GHASH input data into it. Instead, ghash() is trivial to split into update part that can be called separately for each segment. Signed-hostap: Jouni Malinen <j@w1.fi>
Diffstat (limited to 'wlantest')
-rw-r--r--wlantest/gcmp.c109
1 files changed, 39 insertions, 70 deletions
diff --git a/wlantest/gcmp.c b/wlantest/gcmp.c
index 86bb2da..935c176 100644
--- a/wlantest/gcmp.c
+++ b/wlantest/gcmp.c
@@ -94,6 +94,13 @@ static void gf_mult(const u8 *x, const u8 *y, u8 *z)
}
+static void ghash_start(u8 *y)
+{
+ /* Y_0 = 0^128 */
+ os_memset(y, 0, 16);
+}
+
+
static void ghash(const u8 *h, const u8 *x, size_t xlen, u8 *y)
{
size_t m, i;
@@ -102,8 +109,6 @@ static void ghash(const u8 *h, const u8 *x, size_t xlen, u8 *y)
m = xlen / 16;
- /* Y_0 = 0^128 */
- os_memset(y, 0, 16);
for (i = 0; i < m; i++) {
/* Y_i = (Y^(i-1) XOR X_i) dot H */
xor_block(y, xpos);
@@ -116,6 +121,22 @@ static void ghash(const u8 *h, const u8 *x, size_t xlen, u8 *y)
os_memcpy(y, tmp, 16);
}
+ if (x + xlen > xpos) {
+ /* Add zero padded last block */
+ size_t last = x + xlen - xpos;
+ os_memcpy(tmp, xpos, last);
+ os_memset(tmp + last, 0, sizeof(tmp) - last);
+
+ /* Y_i = (Y^(i-1) XOR X_i) dot H */
+ xor_block(y, tmp);
+
+ /* dot operation:
+ * multiplication operation for binary Galois (finite) field of
+ * 2^128 elements */
+ gf_mult(y, h, tmp);
+ os_memcpy(y, tmp, 16);
+ }
+
/* Return Y_m */
}
@@ -160,12 +181,10 @@ static int aes_gcm_ae(const u8 *key, const u8 *iv,
const u8 *aad, size_t aad_len,
u8 *crypt, u8 *tag)
{
- u8 *auth, *apos;
u8 H[AES_BLOCK_SIZE];
u8 J0[AES_BLOCK_SIZE];
- u8 S[16];
+ u8 S[16], len_buf[16];
void *aes;
- size_t padlen;
size_t iv_len = 12;
aes = aes_encrypt_init(key, 16);
@@ -192,38 +211,14 @@ static int aes_gcm_ae(const u8 *key, const u8 *iv,
* 5. S = GHASH_H(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64)
* (i.e., zero padded to block size A || C and lengths of each in bits)
*/
- auth = os_malloc(32 + 16 + plain_len + 8 + 8);
- if (auth == NULL) {
- aes_encrypt_deinit(aes);
- return -1;
- }
+ ghash_start(S);
+ ghash(H, aad, aad_len, S);
+ ghash(H, crypt, plain_len, S);
+ WPA_PUT_BE64(len_buf, aad_len * 8);
+ WPA_PUT_BE64(len_buf + 8, plain_len * 8);
+ ghash(H, len_buf, sizeof(len_buf), S);
- apos = auth;
-
- /* Zero-padded AAD */
- os_memcpy(apos, aad, aad_len);
- apos += aad_len;
- padlen = (16 - aad_len % 16) % 16;
- os_memset(apos, 0, padlen);
- apos += padlen;
-
- /* Zero-padded C */
- os_memcpy(apos, crypt, plain_len);
- apos += plain_len;
- padlen = (16 - plain_len % 16) % 16;
- os_memset(apos, 0, padlen);
- apos += padlen;
-
- /* Length of AAD and C in bits */
- WPA_PUT_BE64(apos, aad_len * 8);
- apos += 8;
- WPA_PUT_BE64(apos, plain_len * 8);
- apos += 8;
-
- wpa_hexdump_key(MSG_EXCESSIVE, "GHASH_H input", auth, apos - auth);
- ghash(H, auth, apos - auth, S);
wpa_hexdump_key(MSG_EXCESSIVE, "S = GHASH_H(...)", S, 16);
- os_free(auth);
/* 6. T = MSB_t(GCTR_K(J_0, S)) */
J0[AES_BLOCK_SIZE - 1] = 0x01;
@@ -245,12 +240,10 @@ static int aes_gcm_ad(const u8 *key, const u8 *iv,
const u8 *aad, size_t aad_len, const u8 *tag,
u8 *plain)
{
- u8 *auth, *apos;
u8 H[AES_BLOCK_SIZE];
u8 J0[AES_BLOCK_SIZE];
- u8 S[16], T[16];
+ u8 S[16], T[16], len_buf[16];
void *aes;
- size_t padlen;
size_t iv_len = 12;
aes = aes_encrypt_init(key, 16);
@@ -260,7 +253,7 @@ static int aes_gcm_ad(const u8 *key, const u8 *iv,
/* 2. Generate hash subkey H = AES_K(0^128) */
os_memset(H, 0, sizeof(H));
aes_encrypt(aes, H, H);
- wpa_hexdump(MSG_EXCESSIVE, "Hash subkey H for GHASH", H, sizeof(H));
+ wpa_hexdump_key(MSG_EXCESSIVE, "Hash subkey H for GHASH", H, sizeof(H));
/* 3. Prepare block J_0 = IV || 0^31 || 1 [len(IV) = 96] */
os_memcpy(J0, iv, iv_len);
@@ -277,38 +270,14 @@ static int aes_gcm_ad(const u8 *key, const u8 *iv,
* 6. S = GHASH_H(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64)
* (i.e., zero padded to block size A || C and lengths of each in bits)
*/
- auth = os_malloc(32 + 16 + crypt_len + 8 + 8);
- if (auth == NULL) {
- aes_encrypt_deinit(aes);
- return -1;
- }
+ ghash_start(S);
+ ghash(H, aad, aad_len, S);
+ ghash(H, crypt, crypt_len, S);
+ WPA_PUT_BE64(len_buf, aad_len * 8);
+ WPA_PUT_BE64(len_buf + 8, crypt_len * 8);
+ ghash(H, len_buf, sizeof(len_buf), S);
- apos = auth;
-
- /* Zero-padded AAD */
- os_memcpy(apos, aad, aad_len);
- apos += aad_len;
- padlen = (16 - aad_len % 16) % 16;
- os_memset(apos, 0, padlen);
- apos += padlen;
-
- /* Zero-padded C */
- os_memcpy(apos, crypt, crypt_len);
- apos += crypt_len;
- padlen = (16 - crypt_len % 16) % 16;
- os_memset(apos, 0, padlen);
- apos += padlen;
-
- /* Length of AAD and C in bits */
- WPA_PUT_BE64(apos, aad_len * 8);
- apos += 8;
- WPA_PUT_BE64(apos, crypt_len * 8);
- apos += 8;
-
- wpa_hexdump(MSG_EXCESSIVE, "GHASH_H input", auth, apos - auth);
- ghash(H, auth, apos - auth, S);
- wpa_hexdump(MSG_EXCESSIVE, "S = GHASH_H(...)", S, 16);
- os_free(auth);
+ wpa_hexdump_key(MSG_EXCESSIVE, "S = GHASH_H(...)", S, 16);
/* 7. T' = MSB_t(GCTR_K(J_0, S)) */
J0[AES_BLOCK_SIZE - 1] = 0x01;