Skip to content

Commit 5f09701

Browse files
authored
Merge pull request #249 from SparkiDev/n_fold_fix_2
n_fold: fix for carries (reverse add)
2 parents bd00908 + 6d68230 commit 5f09701

2 files changed

Lines changed: 157 additions & 91 deletions

File tree

src/wp_krb5kdf.c

Lines changed: 99 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -292,84 +292,134 @@ static int wp_kdf_krb5kdf_expected_key_size(wp_Krb5kdfCtx* ctx)
292292
* s[l] = (constant rot 13*(l/K))[l%k]
293293
* block[l % N] += s[l] (with carry)
294294
* finally add carry if any
295+
*
296+
* @param [in] block Block to fill with constant.
297+
* @param [in] blocksize Size of block in bytes.
298+
* @param [in] constant Constant to use for fill.
299+
* @param [in] constant_len Length of constant in bytes. Not zero and less
300+
* than or equal to blocksize.
295301
*/
296302
static void n_fold(unsigned char *block, unsigned int blocksize,
297303
const unsigned char *constant, size_t constant_len)
298304
{
299-
unsigned int cnt;
300-
unsigned int i;
305+
unsigned int const_len = (unsigned int)constant_len;
301306
unsigned int a;
302307
unsigned int b;
308+
unsigned int cnt;
303309
unsigned int carry;
304-
unsigned int rot;
305310
unsigned int bi;
306-
unsigned int const_len = (unsigned int)constant_len;
311+
unsigned int rot;
312+
unsigned int i;
313+
314+
/* Copy in unrotated constant first. */
315+
XMEMCPY(block, constant, constant_len);
307316

308317
/* If equal size then only one unrotated copy of constant needed. */
309318
if (blocksize == const_len) {
310-
XMEMCPY(block, constant, constant_len);
311319
return;
312320
}
313321

314-
/* Compute GCD of constant_len and blocksize. */
315-
a = blocksize;
316-
b = const_len;
317-
while (b != 0) {
322+
/* Compute first iteration of GCD of constant_len and blocksize. */
323+
a = const_len;
324+
b = blocksize % const_len;
325+
326+
if (b == 0) {
327+
/* Fill rest of block with rotated constant - no adding. */
328+
/* First rotate amount. */
329+
rot = 13;
330+
for (i = const_len; i < blocksize; i += const_len) {
331+
unsigned int j;
332+
/* Calculate first index into constant to rotate. */
333+
unsigned int ci = (i - (rot >> 3) - 1) % const_len;
334+
/* Calculate amount to rotate right and left. */
335+
unsigned char rr = rot & 0x7;
336+
unsigned char rl = 8 - rr;
337+
/* Load first constant value - large type to handle shift 8. */
338+
unsigned int cv = constant[ci];
339+
340+
for (j = 0; j < const_len; j++) {
341+
/* Get rotated constant buffer value. */
342+
block[i + j] = (unsigned char)(cv << rl);
343+
/* Calculate next constant index. */
344+
ci = (ci + 1) % const_len;
345+
/* Load next constant value. */
346+
cv = constant[ci];
347+
/* OR in second rotated value. */
348+
block[i + j] |= (unsigned char)(cv >> rr);
349+
}
350+
/* Update rotate amount. */
351+
rot += 13;
352+
}
353+
return;
354+
}
355+
356+
/* Complete computation of GCD of constant_len and blocksize. */
357+
do {
318358
unsigned int t = b;
319359
b = a % b;
320360
a = t;
321-
}
361+
} while (b != 0);
322362
/* Calculate LCM of constant_len and blocksize. */
323363
cnt = (const_len * blocksize) / a;
324364

325-
/* Start with constant un-rotated and then add to zero for the rest. */
326-
XMEMCPY(block, constant, constant_len);
365+
/* Set rest to zero for add. */
327366
XMEMSET(block + constant_len, 0, blocksize - constant_len);
328367

329368
/* No initial carry. */
330369
carry = 0;
331-
/* First rotation is 13 bits. */
332-
rot = 13;
333-
/* Starting block index - constant_len <= blocksize. */
334-
bi = const_len;
370+
/* Last block is first as we are adding in reverse. */
371+
bi = blocksize - 1;
372+
/* Rotation count for when adding last constant. */
373+
rot = 13 * ((cnt - const_len) / const_len);
335374
/* Do one constant at a time - cnt is a multiple of constant_len. */
336-
for (i = const_len; i < cnt; i += const_len) {
337-
unsigned int j;
338-
/* Calculate first index into constant to rotate. */
339-
unsigned int ci = ((cnt - (rot >> 3)) - 1) % const_len;
340-
/* Calculate amount to rotate right and left. */
341-
unsigned char rr = rot & 0x7;
342-
unsigned char rl = 8 - rr;
343-
344-
/* Add in constant buffer to block. */
345-
for (j = 0; j < const_len; j++) {
346-
/* Rotated constant value. */
347-
unsigned char rcv;
348-
349-
/* Get rotated constant buffer value. */
350-
rcv = (unsigned char)(constant[ci] << rl);
351-
ci = (ci + 1) % const_len;
352-
rcv |= (unsigned char)(constant[ci] >> rr);
353-
354-
/* Add block value and rotated constant value to previous carry. */
355-
carry += block[bi];
356-
carry += rcv;
357-
/* Store new block value. */
358-
block[bi] = (unsigned char)(carry & 0xff);
359-
/* Get carry. */
360-
carry >>= 8;
361-
362-
/* Next block index. */
363-
bi = (bi + 1) % blocksize;
364-
}
365-
rot += 13;
375+
for (i = cnt - const_len; i >= const_len; i -= const_len) {
376+
int j;
377+
/* Calculate last index into constant to rotate. */
378+
unsigned int ci = (i - (rot >> 3) - 1) % const_len;
379+
/* Calculate amount to rotate right and left. */
380+
unsigned char rr = rot & 0x7;
381+
unsigned char rl = 8 - rr;
382+
/* Load first constant value - large type to handle shift 8. */
383+
unsigned int cv = constant[ci];
384+
385+
/* Add in constant buffer to block. */
386+
for (j = const_len - 1; j >= 0; j--) {
387+
/* Rotated constant value. */
388+
unsigned char rcv;
389+
390+
/* Get rotated constant buffer value. */
391+
rcv = (unsigned char)(cv >> rr);
392+
/* Calculate next constant index. */
393+
ci = (ci + (const_len - 1)) % const_len;
394+
/* Load next constant value. */
395+
cv = constant[ci];
396+
/* OR in second rotated value. */
397+
rcv |= (unsigned char)(cv << rl);
398+
399+
/* Add block value and rotated constant value to previous carry. */
400+
carry += block[bi];
401+
carry += rcv;
402+
/* Store new block value. */
403+
block[bi] = (unsigned char)(carry & 0xff);
404+
/* Get carry. */
405+
carry >>= 8;
406+
/* Previous block index. */
407+
bi = (bi + (blocksize - 1)) % blocksize;
408+
}
409+
/* Calculate rotation for previous constant block. */
410+
rot -= 13;
366411
}
367412

368413
/* Final carry pass. */
369-
for (i = 0; (i < blocksize) && (carry > 0); i++) {
370-
carry += block[i];
371-
block[i] = (unsigned char)(carry & 0xff);
414+
while (carry > 0) {
415+
/* Add block value to previous carry. */
416+
carry += block[bi];
417+
/* Store new block value. */
418+
block[bi] = (unsigned char)(carry & 0xff);
419+
/* Get carry. */
372420
carry >>= 8;
421+
/* Previous block index. */
422+
bi = (bi + (blocksize - 1)) % blocksize;
373423
}
374424
}
375425

test/test_krb5kdf.c

Lines changed: 58 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,25 @@ static int test_krb5kdf_error_cases(OSSL_LIB_CTX* libCtx)
113113
}
114114
PRINT_MSG("Negative test passed - KRB5KDF correctly rejected wrong key size for AES-256-CBC");
115115

116+
PRINT_MSG("Testing KRB5KDF error case - 0 length constant");
117+
/* This should fail since AES-256 key size is 32 bytes */
118+
err = test_krb5kdf_calc(libCtx, key, sizeof(key), "AES-256-CBC",
119+
inKey16, sizeof(inKey16), constant, 0);
120+
if (err == 0) {
121+
/* If we get here, the test failed because it should have errored */
122+
PRINT_MSG("FAILED: KRB5KDF accepted 0 length constant");
123+
return 1;
124+
}
125+
PRINT_MSG("Negative test passed - KRB5KDF correctly rejected 0 length constant");
126+
116127
return 0;
117128
}
118129

119130
/* Test vectors */
120131
static int test_krb5kdf_vector(void)
121132
{
122133
int err = 0;
134+
int i;
123135
unsigned char oKey[32];
124136
unsigned char wKey[32];
125137
/* Test vector - AES-128-CBC */
@@ -135,51 +147,55 @@ static int test_krb5kdf_vector(void)
135147
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
136148
};
137149
unsigned char constant[] = {
150+
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
138151
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
139152
};
140153

141-
/* Test AES-128-CBC */
142-
PRINT_MSG("Testing KRB5KDF with OpenSSL - AES-128-CBC");
143-
err = test_krb5kdf_calc(osslLibCtx, oKey, 16, "AES-128-CBC",
144-
inKey128, sizeof(inKey128), constant, sizeof(constant));
145-
if (err == 1) {
146-
PRINT_MSG("FAILED OpenSSL - AES-128-CBC");
147-
return err;
148-
}
149-
PRINT_MSG("Testing KRB5KDF with wolfSSL - AES-128-CBC");
150-
err = test_krb5kdf_calc(wpLibCtx, wKey, 16, "AES-128-CBC",
151-
inKey128, sizeof(inKey128), constant, sizeof(constant));
152-
if (err == 1) {
153-
PRINT_MSG("FAILED wolfSSL - AES-128-CBC");
154-
return err;
155-
}
156-
if (memcmp(oKey, wKey, 16) != 0) {
157-
PRINT_MSG("FAILED, wolfSSL and OpenSSL derived different keys");
158-
PRINT_BUFFER("OpenSSL key", oKey, 16);
159-
PRINT_BUFFER("wolfSSL key", wKey, 16);
160-
return 1;
161-
}
162-
163-
/* Test AES-256-CBC */
164-
PRINT_MSG("Testing KRB5KDF with OpenSSL - AES-256-CBC");
165-
err = test_krb5kdf_calc(osslLibCtx, oKey, 32, "AES-256-CBC",
166-
inKey256, sizeof(inKey256), constant, sizeof(constant));
167-
if (err == 1) {
168-
PRINT_MSG("FAILED OpenSSL - AES-256-CBC");
169-
return err;
170-
}
171-
PRINT_MSG("Testing KRB5KDF with wolfSSL - AES-256-CBC");
172-
err = test_krb5kdf_calc(wpLibCtx, wKey, 32, "AES-256-CBC",
173-
inKey256, sizeof(inKey256), constant, sizeof(constant));
174-
if (err == 1) {
175-
PRINT_MSG("FAILED wolfSSL - AES-256-CBC");
176-
return err;
177-
}
178-
if (memcmp(oKey, wKey, 32) != 0) {
179-
PRINT_MSG("FAILED, wolfSSL and OpenSSL derived different keys");
180-
PRINT_BUFFER("OpenSSL key", oKey, 32);
181-
PRINT_BUFFER("wolfSSL key", wKey, 32);
182-
return 1;
154+
for (i = 1; i < (int)sizeof(constant); i++) {
155+
PRINT_MSG("Constant Length: %d", i);
156+
/* Test AES-128-CBC */
157+
PRINT_MSG("Testing KRB5KDF with OpenSSL - AES-128-CBC");
158+
err = test_krb5kdf_calc(osslLibCtx, oKey, 16, "AES-128-CBC",
159+
inKey128, sizeof(inKey128), constant, i);
160+
if (err == 1) {
161+
PRINT_MSG("FAILED OpenSSL - AES-128-CBC");
162+
return err;
163+
}
164+
PRINT_MSG("Testing KRB5KDF with wolfSSL - AES-128-CBC");
165+
err = test_krb5kdf_calc(wpLibCtx, wKey, 16, "AES-128-CBC",
166+
inKey128, sizeof(inKey128), constant, i);
167+
if (err == 1) {
168+
PRINT_MSG("FAILED wolfSSL - AES-128-CBC");
169+
return err;
170+
}
171+
if (memcmp(oKey, wKey, 16) != 0) {
172+
PRINT_MSG("FAILED, wolfSSL and OpenSSL derived different keys");
173+
PRINT_BUFFER("OpenSSL key", oKey, 16);
174+
PRINT_BUFFER("wolfSSL key", wKey, 16);
175+
return 1;
176+
}
177+
178+
/* Test AES-256-CBC */
179+
PRINT_MSG("Testing KRB5KDF with OpenSSL - AES-256-CBC");
180+
err = test_krb5kdf_calc(osslLibCtx, oKey, 32, "AES-256-CBC",
181+
inKey256, sizeof(inKey256), constant, i);
182+
if (err == 1) {
183+
PRINT_MSG("FAILED OpenSSL - AES-256-CBC");
184+
return err;
185+
}
186+
PRINT_MSG("Testing KRB5KDF with wolfSSL - AES-256-CBC");
187+
err = test_krb5kdf_calc(wpLibCtx, wKey, 32, "AES-256-CBC",
188+
inKey256, sizeof(inKey256), constant, i);
189+
if (err == 1) {
190+
PRINT_MSG("FAILED wolfSSL - AES-256-CBC");
191+
return err;
192+
}
193+
if (memcmp(oKey, wKey, 32) != 0) {
194+
PRINT_MSG("FAILED, wolfSSL and OpenSSL derived different keys");
195+
PRINT_BUFFER("OpenSSL key", oKey, 32);
196+
PRINT_BUFFER("wolfSSL key", wKey, 32);
197+
return 1;
198+
}
183199
}
184200

185201
return err;

0 commit comments

Comments
 (0)