Example #1
0
/* 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);
}
Example #2
0
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;
}
Example #3
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!");
}
Example #8
0
/**
  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;
}