aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2008-05-08 14:51:37 +0000
committerMartin Willi <martin@strongswan.org>2008-05-08 14:51:37 +0000
commit0f074a4344f002fa3f1440fbcdfc5b28ce0b5afb (patch)
tree019d9b9fe1f38e4f1f42f84e6eb9dd8107beb5ae
parentaffd7a90bade50f5194ef730ecf3a7810cecac5a (diff)
downloadstrongswan-0f074a4344f002fa3f1440fbcdfc5b28ce0b5afb.tar.bz2
strongswan-0f074a4344f002fa3f1440fbcdfc5b28ce0b5afb.tar.xz
implemented append mode for xcbc, testcase
-rw-r--r--src/charon/plugins/unit_tester/tests/test_aes.c61
-rw-r--r--src/libstrongswan/plugins/xcbc/xcbc.c138
2 files changed, 163 insertions, 36 deletions
diff --git a/src/charon/plugins/unit_tester/tests/test_aes.c b/src/charon/plugins/unit_tester/tests/test_aes.c
index 5b69dc25d..06e891d83 100644
--- a/src/charon/plugins/unit_tester/tests/test_aes.c
+++ b/src/charon/plugins/unit_tester/tests/test_aes.c
@@ -178,7 +178,7 @@ static bool do_xcbc_test(u_int8_t *key, size_t keylen, u_int8_t *mac,
prf_t *prf;
u_int8_t res[16];
- prf = lib->crypto->create_prf(lib->crypto, PRF_AES128_CBC);
+ prf = lib->crypto->create_prf(lib->crypto, PRF_AES128_XCBC);
if (!prf)
{
return FALSE;
@@ -403,6 +403,65 @@ bool test_aes_xcbc()
{
return FALSE;
}
+
+
+ /* Test Case #10 : AES-XCBC-MAC-96 with 32-byte input using append mode
+ * Key (K) : 000102030405060708090a0b0c0d0e0f
+ * Message (M) : 000102030405060708090a0b0c0d0e0f10111213141516171819
+ * 1a1b1c1d1e1f
+ * AES-XCBC-MAC : f54f0ec8d2b9f3d36807734bd5283fd4
+ * AES-XCBC-MAC-96: f54f0ec8d2b9f3d36807734b
+ */
+ u_char key10[] = {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
+ };
+ u_char plain10[] = {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
+ };
+ u_char mac10[] = {
+ 0xf5,0x4f,0x0e,0xc8,0xd2,0xb9,0xf3,0xd3,
+ 0x68,0x07,0x73,0x4b,0xd5,0x28,0x3f,0xd4
+ };
+ int i;
+ prf_t *prf = lib->crypto->create_prf(lib->crypto, PRF_AES128_XCBC);
+ u_char res[16];
+ if (!prf)
+ {
+ return FALSE;
+ }
+ prf->set_key(prf, chunk_create(key10, sizeof(key10)));
+ for (i = 0; i < 4; i++)
+ { /* bytes 0 - 3, 1 byte at once */
+ prf->get_bytes(prf, chunk_create(plain10 + i, 1), NULL);
+ }
+ for (i = 4; i < 5; i+=8)
+ { /* bytes 4 - 11, at once */
+ prf->get_bytes(prf, chunk_create(plain10 + i, 8), NULL);
+ }
+ for (i = 12; i < 24; i+=4)
+ { /* bytes 12 - 23, in blocks of 4 */
+ prf->get_bytes(prf, chunk_create(plain10 + i, 4), NULL);
+ }
+ for (i = 0; i < 4; i++)
+ { /* 4 zero blobs */
+ prf->get_bytes(prf, chunk_create(NULL, 0), NULL);
+ }
+ for (i = 24; i < 25; i+=8)
+ { /* bytes 24 - 32, at once */
+ prf->get_bytes(prf, chunk_create(plain10 + i, 8), res);
+ }
+ if (!memeq(res, mac10, 16))
+ {
+ DBG1(DBG_CFG, "expected %b\ngot %b", mac10, 16, res, 16);
+ prf->destroy(prf);
+ return FALSE;
+ }
+ prf->destroy(prf);
+
return TRUE;
}
diff --git a/src/libstrongswan/plugins/xcbc/xcbc.c b/src/libstrongswan/plugins/xcbc/xcbc.c
index dc1398950..ab37eca40 100644
--- a/src/libstrongswan/plugins/xcbc/xcbc.c
+++ b/src/libstrongswan/plugins/xcbc/xcbc.c
@@ -53,57 +53,96 @@ struct private_xcbc_t {
* k3
*/
u_int8_t *k3;
+
+ /**
+ * E
+ */
+ u_int8_t *e;
+
+ /**
+ * remaining, unprocessed bytes in append mode
+ */
+ u_int8_t *remaining;
+
+ /**
+ * number of bytes in remaining
+ */
+ int remaining_bytes;
+
+ /**
+ * TRUE if we have zero bytes to xcbc in final()
+ */
+ bool zero;
};
/**
- * Implementation of xcbc_t.get_mac.
+ * xcbc supplied data, but do not run final operation
*/
-static void get_mac(private_xcbc_t *this, chunk_t data, u_int8_t *e)
+static void update(private_xcbc_t *this, chunk_t data)
{
- int n, i, padding;
- u_int8_t *m;
chunk_t iv;
- if (e == NULL)
+ if (data.len)
{
- DBG1("XCBC append mode not implemented!");
- /* TODO: append mode */
- return;
+ this->zero = FALSE;
}
- n = data.len / this->b;
- padding = data.len % this->b;
- if (padding || data.len == 0)
- { /* do an additional block if we have padding or zero-length data */
- n++;
+ if (this->remaining_bytes + data.len <= this->b)
+ { /* no complete block, just copy into remaining */
+ memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len);
+ this->remaining_bytes += data.len;
+ return;
}
+
iv = chunk_alloca(this->b);
memset(iv.ptr, 0, iv.len);
- m = data.ptr;
-
- /* (2) Define E[0] = 0x00000000000000000000000000000000 */
- memset(e, 0, this->b);
/* (3) For each block M[i], where i = 1 ... n-1:
- * XOR M[i] with E[i-1], then encrypt the result with Key K1,
- * yielding E[i].
- */
- for (i = 1; i < n; i++)
+ * XOR M[i] with E[i-1], then encrypt the result with Key K1,
+ * yielding E[i].
+ */
+
+ /* append data to remaining bytes, process block M[1] */
+ memcpy(this->remaining + this->remaining_bytes, data.ptr,
+ this->b - this->remaining_bytes);
+ data = chunk_skip(data, this->b - this->remaining_bytes);
+ memxor(this->e, this->remaining, this->b);
+ this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL);
+
+ /* process blocks M[2] ... M[n-1] */
+ while (data.len > this->b)
{
- memxor(e, m + (i - 1) * this->b, this->b);
- this->k1->encrypt(this->k1, chunk_create(e, this->b), iv, NULL);
+ memcpy(this->remaining, data.ptr, this->b);
+ data = chunk_skip(data, this->b);
+ memxor(this->e, this->remaining, this->b);
+ this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL);
}
+ /* store remaining bytes of block M[n] */
+ memcpy(this->remaining, data.ptr, data.len);
+ this->remaining_bytes = data.len;
+}
+
+/**
+ * run last round, data is in this->e
+ */
+static void final(private_xcbc_t *this, u_int8_t *out)
+{
+ chunk_t iv;
+
+ iv = chunk_alloca(this->b);
+ memset(iv.ptr, 0, iv.len);
+
/* (4) For block M[n]: */
- if (data.len && padding == 0)
+ if (this->remaining_bytes == this->b && !this->zero)
{
/* a) If the blocksize of M[n] is 128 bits:
* XOR M[n] with E[n-1] and Key K2, then encrypt the result with
* Key K1, yielding E[n].
*/
- memxor(e, m + (i - 1) * this->b, this->b);
- memxor(e, this->k2, this->b);
- this->k1->encrypt(this->k1, chunk_create(e, this->b), iv, NULL);
+ memxor(this->e, this->remaining, this->b);
+ memxor(this->e, this->k2, this->b);
+ this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL);
}
else
{
@@ -113,19 +152,41 @@ static void get_mac(private_xcbc_t *this, chunk_t data, u_int8_t *e)
* "0" bits (possibly none) required to increase M[n]'s
* blocksize to 128 bits.
*/
- u_int8_t *mn = alloca(this->b);
- memcpy(mn, m + (n - 1) * this->b, padding);
- mn[padding] = 0x80;
- while (++padding < this->b)
+ if (this->remaining_bytes < this->b)
{
- mn[padding] = 0x00;
+ this->remaining[this->remaining_bytes] = 0x80;
+ while (++this->remaining_bytes < this->b)
+ {
+ this->remaining[this->remaining_bytes] = 0x00;
+ }
}
/* ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result
* with Key K1, yielding E[n].
*/
- memxor(e, mn, this->b);
- memxor(e, this->k3, this->b);
- this->k1->encrypt(this->k1, chunk_create(e, this->b), iv, NULL);
+ memxor(this->e, this->remaining, this->b);
+ memxor(this->e, this->k3, this->b);
+ this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL);
+ }
+
+ memcpy(out, this->e, this->b);
+
+ /* (2) Define E[0] = 0x00000000000000000000000000000000 */
+ memset(this->e, 0, this->b);
+ this->remaining_bytes = 0;
+ this->zero = TRUE;
+}
+
+/**
+ * Implementation of xcbc_t.get_mac.
+ */
+static void get_mac(private_xcbc_t *this, chunk_t data, u_int8_t *out)
+{
+ /* update E, do not process last block */
+ update(this, data);
+
+ if (out)
+ { /* if not in append mode, process last block and output result */
+ final(this, out);
}
}
@@ -192,6 +253,8 @@ static void destroy(private_xcbc_t *this)
this->k1->destroy(this->k1);
free(this->k2);
free(this->k3);
+ free(this->e);
+ free(this->remaining);
free(this);
}
@@ -225,6 +288,11 @@ xcbc_t *xcbc_create(encryption_algorithm_t algo, size_t key_size)
this->k1 = crypter;
this->k2 = malloc(this->b);
this->k3 = malloc(this->b);
+ this->e = malloc(this->b);
+ memset(this->e, 0, this->b);
+ this->remaining = malloc(this->b);
+ this->remaining_bytes = 0;
+ this->zero = TRUE;
return &this->xcbc;
}