/* AES CBC Decrypt */ int CRYPT_AES_CBC_Decrypt(CRYPT_AES_CTX* aes, unsigned char* out, const unsigned char* in, unsigned int inSz) { if (aes == NULL || out == NULL || in == NULL) return BAD_FUNC_ARG; return AesCbcDecrypt((Aes*)aes, out, in, inSz); }
int aes_test() { Aes enc; Aes dec; const byte msg[] = { /* "Now is the time for all " w/o trailing 0 */ 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 }; const byte verify[] = { 0x95,0x94,0x92,0x57,0x5f,0x42,0x81,0x53, 0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb }; byte key[] = "0123456789abcdef "; /* align */ byte iv[] = "1234567890abcdef "; /* align */ byte cipher[AES_BLOCK_SIZE]; byte plain [AES_BLOCK_SIZE]; AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); AesSetKey(&dec, key, AES_BLOCK_SIZE, iv, AES_DECRYPTION); AesCbcEncrypt(&enc, cipher, msg, AES_BLOCK_SIZE); AesCbcDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE); if (memcmp(plain, msg, AES_BLOCK_SIZE)) return -60; if (memcmp(cipher, verify, AES_BLOCK_SIZE)) return -61; return 0; }
/* check mcapi aes cbc */ static int check_aescbc(void) { CRYPT_AES_CTX mcAes; Aes defAes; int ret; byte out1[AES_TEST_SIZE]; byte out2[AES_TEST_SIZE]; strncpy((char*)key, "1234567890abcdefghijklmnopqrstuv", 32); strncpy((char*)iv, "1234567890abcdef", 16); /* 128 cbc encrypt */ ret = CRYPT_AES_KeySet(&mcAes, key, 16, iv, CRYPT_AES_ENCRYPTION); if (ret != 0) { printf("mcapi aes-128 key set failed\n"); return -1; } ret = AesSetKey(&defAes, key, 16, iv, AES_ENCRYPTION); if (ret != 0) { printf("default aes-128 key set failed\n"); return -1; } ret = CRYPT_AES_CBC_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); if (ret != 0) { printf("mcapi aes-128 cbc encrypt failed\n"); return -1; } AesCbcEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { printf("mcapi aes-128 cbc encrypt cmp failed\n"); return -1; } /* 128 cbc decrypt */ ret = CRYPT_AES_KeySet(&mcAes, key, 16, iv, CRYPT_AES_DECRYPTION); if (ret != 0) { printf("mcapi aes-128 key set failed\n"); return -1; } ret = AesSetKey(&defAes, key, 16, iv, DES_DECRYPTION); if (ret != 0) { printf("default aes-128 key set failed\n"); return -1; } ret = CRYPT_AES_CBC_Decrypt(&mcAes, out2, out1, AES_TEST_SIZE); if (ret != 0) { printf("mcapi aes-128 cbc decrypt failed\n"); return -1; } AesCbcDecrypt(&defAes, out1, out1, AES_TEST_SIZE); if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { printf("mcapi aes-128 cbc decrypt cmp failed\n"); return -1; } if (memcmp(out1, ourData, AES_TEST_SIZE) != 0) { printf("mcapi aes-128 cbc decrypt orig cmp failed\n"); return -1; } /* 192 cbc encrypt */ ret = CRYPT_AES_KeySet(&mcAes, key, 24, iv, CRYPT_AES_ENCRYPTION); if (ret != 0) { printf("mcapi aes-192 key set failed\n"); return -1; } ret = AesSetKey(&defAes, key, 24, iv, AES_ENCRYPTION); if (ret != 0) { printf("default aes-192 key set failed\n"); return -1; } ret = CRYPT_AES_CBC_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); if (ret != 0) { printf("mcapi aes-192 cbc encrypt failed\n"); return -1; } AesCbcEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { printf("mcapi aes-192 cbc encrypt cmp failed\n"); return -1; } /* 192 cbc decrypt */ ret = CRYPT_AES_KeySet(&mcAes, key, 24, iv, CRYPT_AES_DECRYPTION); if (ret != 0) { printf("mcapi aes-192 key set failed\n"); return -1; } ret = AesSetKey(&defAes, key, 24, iv, AES_DECRYPTION); if (ret != 0) { printf("default aes-192 key set failed\n"); return -1; } ret = CRYPT_AES_CBC_Decrypt(&mcAes, out2, out1, AES_TEST_SIZE); if (ret != 0) { printf("mcapi aes-192 cbc decrypt failed\n"); return -1; } AesCbcDecrypt(&defAes, out1, out1, AES_TEST_SIZE); if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { printf("mcapi aes-192 cbc decrypt cmp failed\n"); return -1; } if (memcmp(out1, ourData, AES_TEST_SIZE) != 0) { printf("mcapi aes-192 cbc decrypt orig cmp failed\n"); return -1; } /* 256 cbc encrypt */ ret = CRYPT_AES_KeySet(&mcAes, key, 32, iv, CRYPT_AES_ENCRYPTION); if (ret != 0) { printf("mcapi aes-256 key set failed\n"); return -1; } ret = AesSetKey(&defAes, key, 32, iv, AES_ENCRYPTION); if (ret != 0) { printf("default aes-256 key set failed\n"); return -1; } ret = CRYPT_AES_CBC_Encrypt(&mcAes, out1, ourData, AES_TEST_SIZE); if (ret != 0) { printf("mcapi aes-256 cbc encrypt failed\n"); return -1; } AesCbcEncrypt(&defAes, out2, ourData, AES_TEST_SIZE); if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { printf("mcapi aes-256 cbc encrypt cmp failed\n"); return -1; } /* 256 cbc decrypt */ ret = CRYPT_AES_KeySet(&mcAes, key, 32, iv, CRYPT_AES_DECRYPTION); if (ret != 0) { printf("mcapi aes-256 key set failed\n"); return -1; } ret = AesSetKey(&defAes, key, 32, iv, AES_DECRYPTION); if (ret != 0) { printf("default aes-256 key set failed\n"); return -1; } ret = CRYPT_AES_CBC_Decrypt(&mcAes, out2, out1, AES_TEST_SIZE); if (ret != 0) { printf("mcapi aes-256 cbc decrypt failed\n"); return -1; } AesCbcDecrypt(&defAes, out1, out1, AES_TEST_SIZE); if (memcmp(out1, out2, AES_TEST_SIZE) != 0) { printf("mcapi aes-256 cbc decrypt cmp failed\n"); return -1; } if (memcmp(out1, ourData, AES_TEST_SIZE) != 0) { printf("mcapi aes-256 cbc decrypt orig cmp failed\n"); return -1; } printf("aes-cbc mcapi test passed\n"); return 0; }
internal MIN_UNIT_TEST_FUNC(TestDhNegotiatedGroups) { printf("Entered Master thread!\n"); pthread_t SlaveThread; i32 Status = pthread_create(&SlaveThread, 0, SlaveEntryPoint, 0); Stopif(Status != 0, "pthread_create failed in TestDhNegotiatedGroups!\n"); pthread_t EveThread; Status = pthread_create(&EveThread, 0, EveEntryPoint, 0); Stopif(Status != 0, "pthread_create failed in TestDhNegotiatedGroups!\n"); // A -> B Send "p" SendMessage(&GlobalSlaveMailbox, (void *)&NIST_RFC_3526_PRIME_1536); // A -> B Send "g" SendMessage(&GlobalSlaveMailbox, (void *)&NIST_RFC_3526_GEN_BIGNUM); // A -> B Send "A" bignum LittleA; // SessionKeyA used as temp bignum to send BigA (copied by B) bignum SessionKeyA; GenRandKeyAndGPowerRandKeyUnchecked(&LittleA, &SessionKeyA, (bignum *)&NIST_RFC_3526_PRIME_1536, (bignum *)&NIST_RFC_3526_GEN_BIGNUM); SendMessage(&GlobalSlaveMailbox, (void *)&SessionKeyA); // B -> A Send "B" bignum BigB; bignum *ReceivedBigB = (bignum *)ReceiveMessage(&GlobalMasterMailbox); BigNumCopyUnchecked(&BigB, ReceivedBigB); AckMessage(&GlobalMasterMailbox); MontModExpRBigNumMax(&SessionKeyA, &BigB, &LittleA, (bignum *)&NIST_RFC_3526_PRIME_1536); u8 MasterPlaintext[DH_MALICIOUS_G_MAX_PLAINTEXT_SIZE_BYTES] = "Master: This is my message!\nYou decrypted it!\n"; u32 MasterCiphertextSizeBytes = strlen((char *)MasterPlaintext) + 1; Stopif(MasterCiphertextSizeBytes > sizeof(MasterPlaintext), "MasterPlaintext buffer overflow\n"); u8 MasterCiphertext[sizeof(MasterPlaintext) + AES_128_BLOCK_LENGTH_BYTES]; u8 MasterIv[AES_128_BLOCK_LENGTH_BYTES]; u8 SessionSymmetricKey[SHA_1_HASH_LENGTH_BYTES]; HashSessionKeyGenIvAndEncrypt(MasterCiphertext, MasterIv, (u8 *)SessionKeyA.Num, sizeof(u64)*SessionKeyA.SizeWords, MasterPlaintext, MasterCiphertextSizeBytes, SessionSymmetricKey); printf("Master SessionSymmetricKey:\n"); PrintArray(SessionSymmetricKey, SHA_1_HASH_LENGTH_BYTES); ciphertext_iv_payload MasterPayload = { .Ciphertext = MasterCiphertext, .CtSizeBytes = MasterCiphertextSizeBytes, .Iv = MasterIv, }; SendMessage(&GlobalSlaveMailbox, (void *)&MasterPayload); ciphertext_iv_payload *SlavePayload = ReceiveMessage(&GlobalMasterMailbox); u8 DecryptedSlavePt[DH_MALICIOUS_G_MAX_PLAINTEXT_SIZE_BYTES]; Stopif(SlavePayload->CtSizeBytes > sizeof(DecryptedSlavePt), "Received ciphertext too large in TestDhNegotiatedGroups!\n"); AesCbcDecrypt(DecryptedSlavePt, SlavePayload->Ciphertext, SlavePayload->CtSizeBytes, SessionSymmetricKey, SlavePayload->Iv); printf("Slave's Message:\n%s", DecryptedSlavePt); AckMessage(&GlobalMasterMailbox); void *Result; Status = pthread_join(SlaveThread, &Result); printf("Slave thread returned %lu\n", (u64)Result); Status = pthread_join(EveThread, &Result); printf("Eve thread returned %lu\n", (u64)Result); }
internal void * SlaveEntryPoint(void *Arg) { Stopif(Arg, "Arg should be 0 in SlaveEntryPoint!\n"); printf("Entered Slave thread!\n"); bignum *SlaveP = (bignum *)ReceiveMessageAndAck(&GlobalSlaveMailbox); bignum *G = (bignum *)ReceiveMessageAndAck(&GlobalSlaveMailbox); printf("Slave G->Num[0]: 0x%lx, G->SizeWords: 0x%x\n", G->Num[0], G->SizeWords); bignum BigA; bignum *ReceivedBigA = (bignum *)ReceiveMessage(&GlobalSlaveMailbox); BigNumCopyUnchecked(&BigA, ReceivedBigA); AckMessage(&GlobalSlaveMailbox); bignum LittleB; bignum SessionKeyB; GenRandKeyAndGPowerRandKeyUnchecked(&LittleB, &SessionKeyB, SlaveP, G); SendMessage(&GlobalMasterMailbox, (void *)&SessionKeyB); MontModExpRBigNumMax(&SessionKeyB, &BigA, &LittleB, (bignum *)&NIST_RFC_3526_PRIME_1536); u8 SlavePlaintext[DH_MALICIOUS_G_MAX_PLAINTEXT_SIZE_BYTES] = "Slave: This is my message... Mwahaha you can't crack it!\n"; u32 SlaveCiphertextSizeBytes = strlen((char *)SlavePlaintext) + 1; Stopif(SlaveCiphertextSizeBytes > sizeof(SlavePlaintext), "SlavePlaintext buffer overflow\n"); u8 SlaveCiphertext[sizeof(SlavePlaintext) + AES_128_BLOCK_LENGTH_BYTES]; u8 SlaveIv[AES_128_BLOCK_LENGTH_BYTES]; u8 SessionSymmetricKey[SHA_1_HASH_LENGTH_BYTES]; HashSessionKeyGenIvAndEncrypt(SlaveCiphertext, SlaveIv, (u8 *)SessionKeyB.Num, sizeof(u64)*SessionKeyB.SizeWords, SlavePlaintext, SlaveCiphertextSizeBytes, SessionSymmetricKey); printf("Slave SessionSymmetricKey:\n"); PrintArray(SessionSymmetricKey, SHA_1_HASH_LENGTH_BYTES); ciphertext_iv_payload *MasterPayload = ReceiveMessage(&GlobalSlaveMailbox); u8 DecryptedMasterPt[DH_MALICIOUS_G_MAX_PLAINTEXT_SIZE_BYTES]; Stopif(MasterPayload->CtSizeBytes > sizeof(DecryptedMasterPt), "Received ciphertext too large in SlaveEntryPoint!\n"); AesCbcDecrypt(DecryptedMasterPt, MasterPayload->Ciphertext, MasterPayload->CtSizeBytes, SessionSymmetricKey, MasterPayload->Iv); AckMessage(&GlobalSlaveMailbox); ciphertext_iv_payload SlavePayload = { .Ciphertext = SlaveCiphertext, .CtSizeBytes = SlaveCiphertextSizeBytes, .Iv = SlaveIv, }; SendMessage(&GlobalMasterMailbox, (void *)&SlavePayload); printf("Master's message:\n%s", DecryptedMasterPt); return (void *)0; }
internal void * EveEntryPoint(void *Arg) { Stopif(Arg, "Arg should be 0 in EveEntryPoint!\n"); EveWaitSlaveMessage("Entered Eve thread!\nEve intercepted A->B send p!\n"); EveInterceptMessage(); printf("Eve intercepted A->B send g!\n"); #if (G_EQUALS_1_ATTACK | G_EQUALS_P_ATTACK | G_EQUALS_P_MINUS_1_ATTACK) GlobalSlaveMailbox.Message = &GlobalEveScratch; #endif // some attack #if G_EQUALS_1_ATTACK // g := 1 BigNumSetToOneUnchecked(&GlobalEveScratch); #elif G_EQUALS_P_ATTACK // g := p BigNumCopyUnchecked(&GlobalEveScratch, (bignum *)&NIST_RFC_3526_PRIME_1536); #elif G_EQUALS_P_MINUS_1_ATTACK // g := p - 1 // TODO(bwd): works half the time... ((-1)^(X*Y) == -1) iff (X*Y) odd BigNumSetToOneUnchecked(&GlobalEveScratch); BigNumSubtract(&GlobalEveScratch, (bignum *)&NIST_RFC_3526_PRIME_1536, &GlobalEveScratch); #endif // some attack GlobalSlaveMailbox.MsgReceived = true; while (!GlobalSlaveMailbox.AckMessage) { } EveWaitSlaveMessage("Eve intercepted A->B send A!\n"); EveInterceptMessage(); u8 SessionSymmetricKey[SHA_1_HASH_LENGTH_BYTES]; Sha1(SessionSymmetricKey, (u8 *)GlobalEveScratch.Num, sizeof(GlobalEveScratch.Num[0])*GlobalEveScratch.SizeWords); printf("Eve SessionSymmetricKey:\n"); PrintArray(SessionSymmetricKey, sizeof(SessionSymmetricKey)); ciphertext_iv_payload *MasterPayload = GlobalSlaveMailbox.Message; u8 DecryptedMasterPt[DH_MALICIOUS_G_MAX_PLAINTEXT_SIZE_BYTES]; Stopif(MasterPayload->CtSizeBytes > sizeof(DecryptedMasterPt), "Received ciphertext too large in EveEntryPoint!\n"); AesCbcDecrypt(DecryptedMasterPt, MasterPayload->Ciphertext, MasterPayload->CtSizeBytes, SessionSymmetricKey, MasterPayload->Iv); printf("Eve intercepted message:\n%s", DecryptedMasterPt); GlobalSlaveMailbox.MsgReceived = true; return (void *)0; }
internal MIN_UNIT_TEST_FUNC(TestMitmKeyFixingAttack) { // A -> B bignum A; GenRandBigNumModNUnchecked(&A, (bignum *)&NIST_RFC_3526_PRIME_1536); MontModExpRBigNumMax((bignum *)GlobalExchangeBuffer, (bignum *)&NIST_RFC_3526_GEN_BIGNUM, &A, (bignum *)&NIST_RFC_3526_PRIME_1536); // B gets session key bignum B; GenRandBigNumModNUnchecked(&B, (bignum *)&NIST_RFC_3526_PRIME_1536); bignum SessionKeyB; MontModExpRBigNumMax(&SessionKeyB, (bignum *)GlobalExchangeBuffer, &B, (bignum *)&NIST_RFC_3526_PRIME_1536); // B -> A MontModExpRBigNumMax((bignum *)GlobalExchangeBuffer, (bignum *)&NIST_RFC_3526_GEN_BIGNUM, &B, (bignum *)&NIST_RFC_3526_PRIME_1536); // A gets session key bignum SessionKeyA; MontModExpRBigNumMax(&SessionKeyA, (bignum *)GlobalExchangeBuffer, &A, (bignum *)&NIST_RFC_3526_PRIME_1536); MinUnitAssert(AreVectorsEqual(SessionKeyA.Num, SessionKeyB.Num, sizeof(u64)*NIST_RFC_3526_PRIME_1536.SizeWords), "SessionKey mismatch in TestMitmKeyFixingAttack!"); // Send AES-CBC(SHA1(s)[0:16], iv=random(16), msg) + iv u8 Message[sizeof(DH_MITM_TEST_MSG_A) + AES_128_BLOCK_LENGTH_BYTES]; memcpy(Message, DH_MITM_TEST_MSG_A, sizeof(DH_MITM_TEST_MSG_A)); u8 IvA[AES_128_BLOCK_LENGTH_BYTES]; u8 SessionSymmetricKey[SHA_1_HASH_LENGTH_BYTES]; HashSessionKeyGenIvAndEncrypt(GlobalExchangeBuffer, IvA, (u8 *)SessionKeyA.Num, sizeof(u64)*SessionKeyA.SizeWords, Message, STR_LEN(DH_MITM_TEST_MSG_A), SessionSymmetricKey); AesCbcDecrypt(Message, GlobalExchangeBuffer, STR_LEN(DH_MITM_TEST_MSG_A), SessionSymmetricKey, IvA); MinUnitAssert(AreVectorsEqual(Message, (u8 *)DH_MITM_TEST_MSG_A, STR_LEN(DH_MITM_TEST_MSG_A)), "Message mismatch in TestMitmKeyFixingAttack!"); // M -> B/A (sends fake p) BigNumCopyUnchecked((bignum *)GlobalExchangeBuffer, (bignum *)&NIST_RFC_3526_PRIME_1536); // B/A get fake session key MontModExpRBigNumMax(&SessionKeyA, (bignum *)GlobalExchangeBuffer, &A, (bignum *)&NIST_RFC_3526_PRIME_1536); Sha1(SessionSymmetricKey, (u8 *)SessionKeyA.Num, sizeof(u64)*SessionKeyA.SizeWords); u8 EveGuessedSymmetricKey[SHA_1_HASH_LENGTH_BYTES]; Sha1(EveGuessedSymmetricKey, (u8 *)"", 0); MinUnitAssert(AreVectorsEqual(EveGuessedSymmetricKey, SessionSymmetricKey, SHA_1_HASH_LENGTH_BYTES), "Guessed symmetric-key mismatch in TestMitmKeyFixingAttack!"); }
/** Validate UEFI-OpenSSL Block Ciphers (Symmetric Crypto) Interfaces. @retval EFI_SUCCESS Validation succeeded. @retval EFI_ABORTED Validation failed. **/ EFI_STATUS ValidateCryptBlockCipher ( VOID ) { UINTN CtxSize; VOID *CipherCtx; UINT8 Encrypt[256]; UINT8 Decrypt[256]; BOOLEAN Status; Print (L"\nUEFI-OpenSSL Block Cipher Engine Testing: "); CtxSize = TdesGetContextSize (); CipherCtx = AllocatePool (CtxSize); Print (L"\n- TDES Validation: "); Print (L"ECB... "); // // TDES ECB Validation // ZeroMem (Encrypt, sizeof (Encrypt)); ZeroMem (Decrypt, sizeof (Decrypt)); Status = TdesInit (CipherCtx, TdesEcbKey, 64); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = TdesEcbEncrypt (CipherCtx, TdesEcbData, 8, Encrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = TdesEcbDecrypt (CipherCtx, Encrypt, 8, Decrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Encrypt, TdesEcbCipher, 8) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Decrypt, TdesEcbData, 8) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } Print (L"EDE2 ECB... "); // // TDES EDE2 ECB Validation // ZeroMem (Encrypt, sizeof (Encrypt)); ZeroMem (Decrypt, sizeof (Decrypt)); Status = TdesInit (CipherCtx, TdesEcbKey, 128); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = TdesEcbEncrypt (CipherCtx, TdesEcbData, 8, Encrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = TdesEcbDecrypt (CipherCtx, Encrypt, 8, Decrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Encrypt, TdesEcb2Cipher, 8) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Decrypt, TdesEcbData, 8) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } Print (L"EDE3 CBC... "); // // TDES EDE3 CBC Validation // ZeroMem (Encrypt, 256); ZeroMem (Decrypt, 256); Status = TdesInit (CipherCtx, TdesCbcKey, 192); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = TdesCbcEncrypt (CipherCtx, TdesCbcData, sizeof (TdesCbcData), TdesCbcIvec, Encrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = TdesCbcDecrypt (CipherCtx, Encrypt, sizeof (TdesCbcData), TdesCbcIvec, Decrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Encrypt, TdesCbc3Cipher, sizeof (TdesCbc3Cipher)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Decrypt, TdesCbcData, sizeof (TdesCbcData)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } Print (L"[Pass]"); FreePool (CipherCtx); CtxSize = AesGetContextSize (); CipherCtx = AllocatePool (CtxSize); Print (L"\n- AES Validation: "); Print (L"ECB-128... "); // // AES-128 ECB Validation // ZeroMem (Encrypt, sizeof (Encrypt)); ZeroMem (Decrypt, sizeof (Decrypt)); Status = AesInit (CipherCtx, Aes128EcbKey, 128); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = AesEcbEncrypt (CipherCtx, Aes128EcbData, sizeof (Aes128EcbData), Encrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = AesEcbDecrypt (CipherCtx, Encrypt, sizeof (Aes128EcbData), Decrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Encrypt, Aes128EcbCipher, sizeof (Aes128EcbCipher)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Decrypt, Aes128EcbData, sizeof (Aes128EcbData)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } Print (L"ECB-192... "); // // AES-192 ECB Validation // ZeroMem (Encrypt, sizeof (Encrypt)); ZeroMem (Decrypt, sizeof (Decrypt)); Status = AesInit (CipherCtx, Aes192EcbKey, 192); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = AesEcbEncrypt (CipherCtx, Aes192EcbData, sizeof (Aes192EcbData), Encrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = AesEcbDecrypt (CipherCtx, Encrypt, sizeof (Aes192EcbData), Decrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Encrypt, Aes192EcbCipher, sizeof (Aes192EcbCipher)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Decrypt, Aes192EcbData, sizeof (Aes192EcbData)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } Print (L"ECB-256... "); // // AES-256 ECB Validation // ZeroMem (Encrypt, sizeof (Encrypt)); ZeroMem (Decrypt, sizeof (Decrypt)); Status = AesInit (CipherCtx, Aes256EcbKey, 256); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = AesEcbEncrypt (CipherCtx, Aes256EcbData, sizeof (Aes256EcbData), Encrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = AesEcbDecrypt (CipherCtx, Encrypt, sizeof (Aes256EcbData), Decrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Encrypt, Aes256EcbCipher, sizeof (Aes256EcbCipher)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Decrypt, Aes256EcbData, sizeof (Aes256EcbData)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } Print (L"CBC-128... "); // // AES-128 CBC Validation // ZeroMem (Encrypt, sizeof (Encrypt)); ZeroMem (Decrypt, sizeof (Decrypt)); Status = AesInit (CipherCtx, Aes128CbcKey, 128); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = AesCbcEncrypt (CipherCtx, Aes128CbcData, sizeof (Aes128CbcData), Aes128CbcIvec, Encrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = AesCbcDecrypt (CipherCtx, Encrypt, sizeof (Aes128CbcData), Aes128CbcIvec, Decrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Encrypt, Aes128CbcCipher, sizeof (Aes128CbcCipher)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Decrypt, Aes128CbcData, sizeof (Aes128CbcData)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } Print (L"[Pass]"); Print (L"\n- ARC4 Validation: "); // // ARC4 Validation // CtxSize = Arc4GetContextSize (); CipherCtx = AllocatePool (CtxSize); ZeroMem (Encrypt, sizeof (Encrypt)); ZeroMem (Decrypt, sizeof (Decrypt)); Status = Arc4Init (CipherCtx, Arc4Key, sizeof (Arc4Key)); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = Arc4Encrypt (CipherCtx, Arc4Data, sizeof (Arc4Data), Encrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = Arc4Reset (CipherCtx); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } Status = Arc4Decrypt (CipherCtx, Encrypt, sizeof (Arc4Data), Decrypt); if (!Status) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Encrypt, Arc4Cipher, sizeof (Arc4Cipher)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } if (CompareMem (Decrypt, Arc4Data, sizeof (Arc4Data)) != 0) { Print (L"[Fail]"); return EFI_ABORTED; } Print (L"[Pass]"); Print (L"\n"); return EFI_SUCCESS; }
// TODO(bwd): Some asserts can move to lower level functions internal MIN_UNIT_TEST_FUNC(TestPaddingOracleDecrypt) { u32 InputStringIndex = rand() % ARRAY_LENGTH(InputStringArray); u32 InputStringLength = InputStringLengths[InputStringIndex]; u8 InputString[MAX_INPUT_PADDED_SIZE]; memcpy(InputString, InputStringArray[InputStringIndex], InputStringLength); u32 Key[AES_128_BLOCK_LENGTH_WORDS]; GenRandUnchecked(Key, ARRAY_LENGTH(Key)); u32 Iv[AES_128_BLOCK_LENGTH_WORDS]; GenRandUnchecked(Iv, ARRAY_LENGTH(Iv)); u8 Ciphertext[MAX_INPUT_PADDED_SIZE]; Stopif(sizeof(Ciphertext) < InputStringLength, "String too long for Ciphertext TestPaddingOracleDecrypt"); u32 PaddedLength = AesCbcEncrypt(Ciphertext, InputString, InputStringLength, (u8 *)Key, (u8 *)Iv); u32 InputStringLengthMod16 = (InputStringLength % AES_128_BLOCK_LENGTH_BYTES); Stopif((PaddedLength < InputStringLength) || ((InputStringLengthMod16 == 0) && (PaddedLength != (InputStringLength + AES_128_BLOCK_LENGTH_BYTES))) || ((InputStringLengthMod16 != 0) && (PaddedLength <= InputStringLength)) || ((PaddedLength % AES_128_BLOCK_LENGTH_BYTES) != 0), "Invalid PaddedLength from AesCbcEncrypt in TestPaddingOracleDecrypt"); u8 Plaintext[MAX_INPUT_PADDED_SIZE]; u8 DecryptScratchBuffer[AES_128_BLOCK_LENGTH_BYTES]; u8 GuessPrevCipherBlock[AES_128_BLOCK_LENGTH_BYTES]; for (u32 PaddedBlocksIndex = 0; PaddedBlocksIndex < (PaddedLength/AES_128_BLOCK_LENGTH_BYTES); ++PaddedBlocksIndex) { u32 BlockOffsetInBytes = AES_128_BLOCK_LENGTH_BYTES*PaddedBlocksIndex; for (i32 CurrentGuessIndex = (AES_128_BLOCK_LENGTH_BYTES - 1); CurrentGuessIndex >= 0; --CurrentGuessIndex) { if (PaddedBlocksIndex == 0) { memcpy(GuessPrevCipherBlock, Iv, AES_128_BLOCK_LENGTH_BYTES); } else { memcpy(GuessPrevCipherBlock, Ciphertext + AES_128_BLOCK_LENGTH_BYTES*(PaddedBlocksIndex - 1), AES_128_BLOCK_LENGTH_BYTES); } u32 CurrentPaddingByteCount = AES_128_BLOCK_LENGTH_BYTES - CurrentGuessIndex; for (u32 GuessPaddingByteIndex = CurrentGuessIndex + 1; GuessPaddingByteIndex < AES_128_BLOCK_LENGTH_BYTES; ++GuessPaddingByteIndex) { GuessPrevCipherBlock[GuessPaddingByteIndex] ^= ((Plaintext[BlockOffsetInBytes + GuessPaddingByteIndex]) ^ CurrentPaddingByteCount); } b32 ByteGuessed = false; u32 GuessByte; for (GuessByte = 0; GuessByte <= 0xFF; ++GuessByte) { u8 CurrentPaddingByte = LowByte(AES_128_BLOCK_LENGTH_BYTES - CurrentGuessIndex); u8 CurrentXorValue = LowByte(GuessByte) ^ CurrentPaddingByte; u8 *CurrentXorByte = ((u8 *)GuessPrevCipherBlock + CurrentGuessIndex); *CurrentXorByte ^= CurrentXorValue; // NOTE(bwd): server padding check AesCbcDecrypt(DecryptScratchBuffer, Ciphertext + BlockOffsetInBytes, sizeof(DecryptScratchBuffer), (u8 *)Key, (u8 *)GuessPrevCipherBlock); *CurrentXorByte ^= CurrentXorValue; u32 StrippedStringLength; u8 *StrippedString = StripPkcs7GetStrippedLength(DecryptScratchBuffer, &StrippedStringLength, AES_128_BLOCK_LENGTH_BYTES); if (StrippedString && (StrippedStringLength == (u32)CurrentGuessIndex)) { ByteGuessed = true; Plaintext[BlockOffsetInBytes + CurrentGuessIndex] = LowByte(GuessByte); break; } } Stopif(!ByteGuessed, "No guess byte found in TestPaddingOracleDecrypt"); } Stopif(memcmp(Plaintext + BlockOffsetInBytes, InputString + BlockOffsetInBytes, AES_128_BLOCK_LENGTH_BYTES) != 0, "Block %d not decrypted correctly", PaddedBlocksIndex); } MinUnitAssert(memcmp(Plaintext, InputString, InputStringLength) == 0, "Plaintext not recovered in TestPaddingOracleDecrypt"); }
/********************* Defination of aes_test() ***************************/ int aes_test(void) { Aes enc; Aes dec; /* Defination of input string to be used AES Enryption */ const byte msg[] = { /*length must be a multiple of 128 bits £¨16 bytes£©*/ 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, }; const byte verify[] = { 0x95,0x94,0x92,0x57,0x5f,0x42,0x81,0x53, 0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb, }; byte key[] = "0123456789abcdef"; /* align Must be 128 bits */ byte iv[] = "1234567890abcdef"; /* align Must be 128 bits */ byte cipher[AES_BLOCK_SIZE * 8]; byte plain [AES_BLOCK_SIZE * 8]; AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); AesSetKey(&dec, key, AES_BLOCK_SIZE, iv, AES_DECRYPTION); /* Encryption process */ AesCbcEncrypt(&enc, cipher, msg, sizeof(msg)); /* Printf cipher text */ printf("The Cipher Text is: "); for(int i=0;i<sizeof(msg);i++) { printf("-%x",cipher[i]); /* Print Cipher Text after encryption */ } printf("\r\n"); printf("\r\n"); /* Decryption process */ AesCbcDecrypt(&dec, plain, cipher, sizeof(cipher)); /* Print plain text */ printf("The Plain Text is: "); for(int i=0;i<sizeof(msg);i++) { printf("-%x",plain[i]); /* Print Plain Text after decryption */ } printf("\r\n"); printf("\r\n"); /* Compare cipher text, generated from encryption, with verify[] predefined */ if (memcmp(cipher, verify, sizeof(msg))) return -1; /* Compare plain text£¬generated from decryption, with msg[] defined */ if (memcmp(plain, msg, sizeof(msg))) return 1; return 0; }