Skip to content

Commit 41b5f60

Browse files
authored
Merge pull request #78 from ColtonWilley/wp_fix_aes_gcm_stream_iv
Fix AES-GCM stream IV handling for openSSH flow
2 parents 5e3c051 + 139d710 commit 41b5f60

File tree

2 files changed

+158
-21
lines changed

2 files changed

+158
-21
lines changed

src/wp_aes_aead.c

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,7 @@ static int wp_aesgcm_get_rand_iv(wp_AeadCtx* ctx, unsigned char* out,
819819
#ifdef WOLFSSL_AESGCM_STREAM
820820
int rc;
821821

822-
rc = wc_AesGcmEncryptInit_ex(&ctx->aes, NULL, 0, ctx->iv,
823-
(word32)ctx->ivLen);
822+
rc = wc_AesGcmInit(&ctx->aes, NULL, 0, ctx->iv, ctx->ivLen);
824823
if (rc != 0) {
825824
ok = 0;
826825
}
@@ -967,23 +966,27 @@ static int wp_aesgcm_einit(wp_AeadCtx* ctx, const unsigned char *key,
967966
if (ok) {
968967
int rc;
969968

970-
if (ivLen == 0) {
971-
if (key != NULL) {
972-
rc = wc_AesGcmSetKey(aes, key, (word32)keyLen);
973-
if (rc != 0) {
974-
ok = 0;
975-
}
976-
}
977-
}
978-
else {
979-
rc = wc_AesGcmEncryptInit(aes, key, (word32)keyLen, iv, (word32)ivLen);
980-
if (rc != 0) {
969+
if (iv != NULL) {
970+
if (ivLen == 0) {
981971
ok = 0;
982972
}
983973
if (ok) {
984974
XMEMCPY(ctx->iv, iv, ivLen);
985975
ctx->ivState = IV_STATE_BUFFERED;
986976
ctx->ivSet = 0;
977+
ctx->ivLen = ivLen;
978+
}
979+
}
980+
if ((ivLen == 0) && (key != NULL)) {
981+
rc = wc_AesGcmSetKey(aes, key, (word32)keyLen);
982+
if (rc != 0) {
983+
ok = 0;
984+
}
985+
}
986+
else if (key != NULL) {
987+
rc = wc_AesGcmEncryptInit(aes, key, (word32)keyLen, iv, (word32)ivLen);
988+
if (rc != 0) {
989+
ok = 0;
987990
}
988991
}
989992
}
@@ -1041,8 +1044,10 @@ static int wp_aesgcm_dinit(wp_AeadCtx *ctx, const unsigned char *key,
10411044
ok = 0;
10421045
}
10431046
#ifdef WOLFSSL_AESGCM_STREAM
1044-
if (ok && (wc_AesGcmDecryptInit(aes, key, (word32)keyLen, iv, (word32)ivLen) != 0)) {
1045-
ok = 0;
1047+
if (ok && key != NULL) {
1048+
if (wc_AesGcmDecryptInit(aes, key, (word32)keyLen, iv, (word32)ivLen) != 0) {
1049+
ok = 0;
1050+
}
10461051
}
10471052
if (ok) {
10481053
XMEMCPY(ctx->iv, iv, ivLen);
@@ -1181,6 +1186,7 @@ static int wp_aesgcm_stream_update(wp_AeadCtx *ctx, unsigned char *out,
11811186
int ok = 1;
11821187
int done = 0;
11831188
size_t oLen = 0;
1189+
int rc;
11841190

11851191
if (ctx->tlsAadLen != UNINITIALISED_SIZET) {
11861192
ok = wp_aesgcm_tls_cipher(ctx, out, outLen, in, inLen);
@@ -1192,7 +1198,17 @@ static int wp_aesgcm_stream_update(wp_AeadCtx *ctx, unsigned char *out,
11921198
}
11931199

11941200
if ((!done) && ok) {
1195-
int rc;
1201+
if (ctx->ivState == IV_STATE_BUFFERED) {
1202+
rc = wc_AesGcmInit(&ctx->aes, NULL, 0, ctx->iv, ctx->ivLen);
1203+
if (rc != 0) {
1204+
ok = 0;
1205+
}
1206+
1207+
ctx->ivState = IV_STATE_COPIED;
1208+
}
1209+
}
1210+
1211+
if ((!done) && ok) {
11961212
const unsigned char* aad = NULL;
11971213
size_t aadLen = 0;
11981214

@@ -1465,11 +1481,13 @@ static int wp_aesgcm_cipher(wp_AeadCtx *ctx, unsigned char *out,
14651481
ok = 0;
14661482
}
14671483
if (ok) {
1468-
ok = wp_aesgcm_stream_update(ctx, out, outLen, outSize, in, inLen);
1469-
}
1470-
if (ok) {
1471-
ok = wp_aesgcm_stream_final(ctx, out + *outLen, &finalLen,
1472-
outSize - *outLen);
1484+
if (in != NULL) {
1485+
ok = wp_aesgcm_stream_update(ctx, out, outLen, outSize, in, inLen);
1486+
}
1487+
else {
1488+
ok = wp_aesgcm_stream_final(ctx, out + *outLen, &finalLen,
1489+
outSize - *outLen);
1490+
}
14731491
}
14741492
if (ok) {
14751493
*outLen += finalLen;

test/test_aestag.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,105 @@ static int test_aes_tag_fixed_enc(const EVP_CIPHER *cipher,
363363
return err;
364364
}
365365

366+
static int test_aes_tag_enc_ossh(const EVP_CIPHER *cipher,
367+
unsigned char *key, unsigned char *iv,
368+
unsigned char *aad, unsigned char *msg, int len, unsigned char *enc,
369+
unsigned char *tag)
370+
{
371+
int err;
372+
EVP_CIPHER_CTX *encCtx;
373+
unsigned int tagLen = 16;
374+
char lastiv[1];
375+
376+
/* Test encryption flow used by openSSH */
377+
err = (encCtx = EVP_CIPHER_CTX_new()) == NULL;
378+
if (err == 0) {
379+
err = EVP_CipherInit(encCtx, cipher, NULL, iv, 1) != 1;
380+
}
381+
if (err == 0) {
382+
err = EVP_CIPHER_CTX_ctrl(encCtx, EVP_CTRL_GCM_SET_IV_FIXED, -1,
383+
iv) != 1;
384+
}
385+
if (err == 0) {
386+
err = EVP_CipherInit(encCtx, NULL, key, NULL, -1) != 1;
387+
}
388+
if (err == 0) {
389+
err = EVP_CIPHER_CTX_ctrl(encCtx, EVP_CTRL_GCM_IV_GEN, 1,
390+
lastiv) != 1;
391+
}
392+
if (err == 0) {
393+
err = EVP_Cipher(encCtx, NULL, aad, (int)strlen((char *)aad)) < 0;
394+
}
395+
if (err == 0) {
396+
err = EVP_Cipher(encCtx, enc, msg, len) < 0;
397+
}
398+
if (err == 0) {
399+
err = EVP_Cipher(encCtx, NULL, NULL, 0) < 0;
400+
}
401+
if (err == 0) {
402+
err = EVP_CIPHER_CTX_ctrl(encCtx, EVP_CTRL_GCM_GET_TAG, tagLen,
403+
tag) != 1;
404+
}
405+
if (err == 0) {
406+
PRINT_BUFFER("Encrypted", enc, len);
407+
PRINT_BUFFER("Tag", tag, 16);
408+
}
409+
410+
EVP_CIPHER_CTX_free(encCtx);
411+
return err;
412+
}
413+
414+
static int test_aes_tag_dec_ossh(const EVP_CIPHER *cipher,
415+
unsigned char *key, unsigned char *iv,
416+
unsigned char *aad, unsigned char *msg, int len, unsigned char *enc,
417+
unsigned char *tag, unsigned char *dec)
418+
{
419+
int err;
420+
EVP_CIPHER_CTX *decCtx;
421+
unsigned int tagLen = 16;
422+
char lastiv[1];
423+
424+
/* Test decryption flow used by openSSH */
425+
err = (decCtx = EVP_CIPHER_CTX_new()) == NULL;
426+
if (err == 0) {
427+
err = EVP_CipherInit(decCtx, cipher, NULL, iv, 0) != 1;
428+
}
429+
if (err == 0) {
430+
err = EVP_CIPHER_CTX_ctrl(decCtx, EVP_CTRL_GCM_SET_IV_FIXED, -1,
431+
iv) != 1;
432+
}
433+
if (err == 0) {
434+
err = EVP_CipherInit(decCtx, NULL, key, NULL, -1) != 1;
435+
}
436+
if (err == 0) {
437+
err = EVP_CIPHER_CTX_ctrl(decCtx, EVP_CTRL_GCM_IV_GEN, 1,
438+
lastiv) != 1;
439+
}
440+
if (err == 0) {
441+
err = EVP_CIPHER_CTX_ctrl(decCtx, EVP_CTRL_GCM_SET_TAG, tagLen,
442+
tag) != 1;
443+
}
444+
if (err == 0) {
445+
err = EVP_Cipher(decCtx, NULL, aad, (int)strlen((char *)aad)) < 0;
446+
}
447+
if (err == 0) {
448+
err = EVP_Cipher(decCtx, dec, enc, len) < 0;
449+
}
450+
if (err == 0) {
451+
err = EVP_Cipher(decCtx, NULL, NULL, 0) < 0;
452+
}
453+
if (err == 0 && dec != NULL && msg != NULL) {
454+
PRINT_BUFFER("Decrypted", dec, len);
455+
456+
if (memcmp(dec, msg, len) != 0) {
457+
err = 1;
458+
}
459+
}
460+
461+
EVP_CIPHER_CTX_free(decCtx);
462+
return err;
463+
}
464+
366465
static int test_aes_tag_fixed(void *data, const char *cipher,
367466
int keyLen, int ivFixedLen, int ivLen)
368467
{
@@ -418,6 +517,26 @@ static int test_aes_tag_fixed(void *data, const char *cipher,
418517
err = test_aes_tag_dec(ocipher, key, iv, ivLen, aad, msg,
419518
sizeof(msg), enc, tag, dec, 0, 0);
420519
}
520+
if (err == 0) {
521+
PRINT_MSG("Encrypt with wolfprovider");
522+
test_aes_tag_enc_ossh(wcipher, key, iv,
523+
aad, msg, sizeof(msg), enc, tag);
524+
}
525+
if (err == 0) {
526+
PRINT_MSG("Decrypt with OpenSSL");
527+
test_aes_tag_dec_ossh(ocipher, key, iv,
528+
aad, msg, sizeof(msg), enc, tag, dec);
529+
}
530+
if (err == 0) {
531+
PRINT_MSG("Encrypt with OpenSSL");
532+
test_aes_tag_enc_ossh(ocipher, key, iv,
533+
aad, msg, sizeof(msg), enc, tag);
534+
}
535+
if (err == 0) {
536+
PRINT_MSG("Decrypt with wolfprovider");
537+
test_aes_tag_dec_ossh(wcipher, key, iv,
538+
aad, msg, sizeof(msg), enc, tag, dec);
539+
}
421540

422541
EVP_CIPHER_free(wcipher);
423542
EVP_CIPHER_free(ocipher);

0 commit comments

Comments
 (0)