Example #1
0
void lrw_gen(void)
{
#ifdef LTC_LRW_MODE
   FILE *out;
   unsigned char tweak[16], key[16], iv[16], buf[1024];
   int x, y, err;
   symmetric_LRW lrw;

   /* initialize default key and tweak */
   for (x = 0; x < 16; x++) {
      tweak[x] = key[x] = iv[x] = x;
   }

   out = fopen("lrw_tv.txt", "w");
   for (x = 16; x < (int)(sizeof(buf)); x += 16) {
       if ((err = lrw_start(find_cipher("aes"), iv, key, 16, tweak, 0, &lrw)) != CRYPT_OK) {
          fprintf(stderr, "Error starting LRW-AES: %s\n", error_to_string(err));
          exit(EXIT_FAILURE);
       }

       /* encrypt incremental */
       for (y = 0; y < x; y++) {
           buf[y] = y & 255;
       }

       if ((err = lrw_encrypt(buf, buf, x, &lrw)) != CRYPT_OK) {
          fprintf(stderr, "Error encrypting with LRW-AES: %s\n", error_to_string(err));
          exit(EXIT_FAILURE);
       }

       /* display it */
       fprintf(out, "%d:", x);
       for (y = 0; y < x; y++) {
          fprintf(out, "%02x", buf[y]);
       }
       fprintf(out, "\n");

       /* reset IV */
       if ((err = lrw_setiv(iv, 16, &lrw)) != CRYPT_OK) {
          fprintf(stderr, "Error setting IV: %s\n", error_to_string(err));
          exit(EXIT_FAILURE);
       }

       /* copy new tweak, iv and key */
       for (y = 0; y < 16; y++) {
          key[y]   = buf[y];
          iv[y]    = buf[(y+16)%x];
          tweak[y] = buf[(y+32)%x];
       }

       if ((err = lrw_decrypt(buf, buf, x, &lrw)) != CRYPT_OK) {
          fprintf(stderr, "Error decrypting with LRW-AES: %s\n", error_to_string(err));
          exit(EXIT_FAILURE);
       }

       /* display it */
       fprintf(out, "%d:", x);
       for (y = 0; y < x; y++) {
          fprintf(out, "%02x", buf[y]);
       }
       fprintf(out, "\n");
       lrw_done(&lrw);
   }
   fclose(out);
#endif
}
Example #2
0
/**
  Test LRW against specs
  @return CRYPT_OK if goodly
*/
int lrw_test(void)
{
#ifndef  LTC_TEST
   return CRYPT_NOP;
#else
   static const struct {
      unsigned char key[16], tweak[16], IV[16], P[16], expected_tweak[16], C[16];
   } tests[] = {

{
{ 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d, 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85 },
{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 },
{ 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f, 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 }
},

{
{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 },
{ 0x35, 0x23, 0xc2, 0xde, 0xc5, 0x69, 0x4f, 0xa8, 0x72, 0xa9, 0xac, 0xa7, 0x0b, 0x2b, 0xee, 0xbc },
{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e },
{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
},

{
{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 },
{ 0x67, 0x53, 0xc9, 0x0c, 0xb7, 0xd8, 0xcd, 0xe5, 0x06, 0xa0, 0x47, 0x78, 0x1a, 0xad, 0x85, 0x11 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e },
{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 },
},

{

{ 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50, 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47 },
{ 0x4e, 0xb5, 0x5d, 0x31, 0x05, 0x97, 0x3a, 0x3f, 0x5e, 0x23, 0xda, 0xfb, 0x5a, 0x45, 0xd6, 0xc0 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },
{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 },
{ 0x18, 0xc9, 0x1f, 0x6d, 0x60, 0x1a, 0x1a, 0x37, 0x5d, 0x0b, 0x0e, 0xf7, 0x3a, 0xd5, 0x74, 0xc4 },
{ 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82, 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 },

}
};

  int idx, err, x;
  symmetric_LRW lrw;
  unsigned char buf[2][16];

  idx = find_cipher("aes");
  if (idx == -1) {
     idx = find_cipher("rijndael");
     if (idx == -1) {
        return CRYPT_NOP;
     }
  }

  for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
     /* schedule it */
     if ((err = lrw_start(idx, tests[x].IV, tests[x].key, 16, tests[x].tweak, 0, &lrw)) != CRYPT_OK) {
        return err;
     }

     /* check pad against expected tweak */
     if (XMEMCMP(tests[x].expected_tweak, lrw.pad, 16)) {
        lrw_done(&lrw);
        return CRYPT_FAIL_TESTVECTOR;
     }

     /* process block */
     if ((err = lrw_encrypt(tests[x].P, buf[0], 16, &lrw)) != CRYPT_OK) {
        lrw_done(&lrw);
        return err;
     }

     if (XMEMCMP(buf[0], tests[x].C, 16)) {
        lrw_done(&lrw);
        return CRYPT_FAIL_TESTVECTOR;
     }

     /* process block */
     if ((err = lrw_setiv(tests[x].IV, 16, &lrw)) != CRYPT_OK) { 
        lrw_done(&lrw);
        return err;
     }

     if ((err = lrw_decrypt(buf[0], buf[1], 16, &lrw)) != CRYPT_OK) {
        lrw_done(&lrw);
        return err;
     }

     if (XMEMCMP(buf[1], tests[x].P, 16)) {
        lrw_done(&lrw);
        return CRYPT_FAIL_TESTVECTOR;
     }
     if ((err = lrw_done(&lrw)) != CRYPT_OK) {
        return err;
     }
   }
   return CRYPT_OK;
#endif
}
// =========================================================================
// Encrypt/Decrypt function
// Note: PlaintextLength must be set to the size of the PlaintextData buffer on
//       entry; on exit, this will be set to the size of the buffer used.
NTSTATUS
ImpCypherCryptData(
    IN      GUID* CypherGUID,
    IN      LARGE_INTEGER SectorID,
    IN      int SectorSize, // In bytes
    IN      int KeyLength,  // In bits
    IN      FREEOTFEBYTE* Key,
    IN      char* KeyASCII,  // ASCII representation of "Key"
    IN      int IVLength,  // In bits
    IN      FREEOTFEBYTE* IV,
    IN      BOOLEAN encryptNotDecrypt,  // TRUE = encrypt; FALSE = decrypt
    IN      int InLength,  // In bytes
    IN      FREEOTFEBYTE* InData,
    OUT     FREEOTFEBYTE* OutData
)
{
    NTSTATUS status = STATUS_SUCCESS;
    // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL
    char ltcNullIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE];
    int cipher;
    symmetric_CBC *cbc;
    symmetric_LRW *lrw;
    symmetric_xts *xts;
    int errnum;
    CYPHER_MODE mode;
    int keySizeUnderlying;
    LARGE_INTEGER blockID64;
    INTEGER_128 blockID128;

    DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDecryptData\n")));

    status = DetermineCypherDetails(
                                    CypherGUID,
                                    &keySizeUnderlying,
                                    &mode
                                   );

    // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL
    if ( (IVLength == 0) || (IV == NULL) )
        {
        FREEOTFE_MEMZERO(&ltcNullIV, sizeof(ltcNullIV));
        IV = (char*)&ltcNullIV;
        }

    // Sanity check on key supplied
    if NT_SUCCESS(status) 
        {
        switch (mode)
            {
            case CYPHER_MODE_CBC:
                {
                if (KeyLength != keySizeUnderlying)
                    {
                    status = STATUS_INVALID_PARAMETER;
                    }

                break;
                }

            case CYPHER_MODE_XTS:
                {
                if (KeyLength != (2 * keySizeUnderlying))
                    {
                    status = STATUS_INVALID_PARAMETER;
                    }

                break;
                }

            case CYPHER_MODE_LRW:
                {
                if (KeyLength != (keySizeUnderlying + (twofish_desc.block_length * 8)))
                    {
                    status = STATUS_INVALID_PARAMETER;
                    }

                break;
                }

            }
        }

    if NT_SUCCESS(status) 
        {
        status = InitLTCCypher(&cipher);
        }

    if NT_SUCCESS(status)
        {
        switch (mode)
            {
            case CYPHER_MODE_CBC:
                {
                cbc = FREEOTFE_MEMALLOC(sizeof(symmetric_CBC));    
                FREEOTFE_MEMZERO(cbc, sizeof(symmetric_CBC));

                // Start a CBC session
                if ((errnum = cbc_start(
                                        cipher, 
                                        IV, 
                                        Key, 
                                        (keySizeUnderlying/8), 
                                        0, 
                                        cbc
                                       )) != CRYPT_OK)
                    {
                    status = STATUS_UNSUCCESSFUL;
                    DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start CBC session (errnum: %d)\n"), errnum));
                    }
                else
                    {
                    if (encryptNotDecrypt)
                        {
                        if ((errnum = cbc_encrypt(
                                                  InData, 
                                                  OutData, 
                                                  InLength, 
                                                  cbc
                                                 )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }
                    else
                        {
                        if ((errnum = cbc_decrypt(
                                              InData, 
                                              OutData, 
                                              InLength, 
                                              cbc
                                             )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }

                    cbc_done(cbc);
                    }

                SecZeroMemory(cbc, sizeof(symmetric_CBC));
                FREEOTFE_FREE(cbc);

                break;
                }

            case CYPHER_MODE_LRW:
                {
                lrw = FREEOTFE_MEMALLOC(sizeof(symmetric_LRW));    
                FREEOTFE_MEMZERO(lrw, sizeof(symmetric_LRW));

                // Generate index in correct format
                // LRW uses:
                //   *) The block index (i.e. the number of 128 bit blocks)
                //   *) The first block has block index 1 - not 0!
                //   *) Bigendian format
                // Note: LTC increments this itself as it processes each block
                SectorIDToBlockIdx_64Bit(SectorID, SectorSize, &blockID64);
                LARGE_INTEGER__To__INTEGER_128_BigEndian(
                                                    blockID64,
                                                    blockID128
                                                   );
                IV = blockID128;

                // Start a LRW session
                if ((errnum = lrw_start(
                                        cipher, 
                                        IV, 
                                        Key, 
                                        (keySizeUnderlying/8), 
                                        // 128 bits tweak key begins after the
                                        // cypher key
                                        (Key + (keySizeUnderlying/8)),
                                        0, 
                                        lrw
                                       )) != CRYPT_OK)
                    {
                    status = STATUS_UNSUCCESSFUL;
                    DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start LRW session (errnum: %d)\n"), errnum));
                    }
                else
                    {
                    if (encryptNotDecrypt)
                        {
                        if ((errnum = lrw_encrypt(
                                                  InData, 
                                                  OutData, 
                                                  InLength, 
                                                  lrw
                                                 )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }
                    else 
                        {
                            if ((errnum = lrw_decrypt(
                                                  InData, 
                                                  OutData, 
                                                  InLength, 
                                                  lrw
                                                 )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }

                    lrw_done(lrw);
                    }

                SecZeroMemory(lrw, sizeof(symmetric_LRW));
                FREEOTFE_FREE(lrw);

                break;
                }

            case CYPHER_MODE_XTS:
                {
                xts = FREEOTFE_MEMALLOC(sizeof(symmetric_xts));    
                FREEOTFE_MEMZERO(xts, sizeof(symmetric_xts));

                // Generate index in correct format
                // XTS uses:
                //   *) The sector index (i.e. the number of N-bit sectors)
                //   *) The first sector is sector 0
                //   *) Littleendian format
                LARGE_INTEGER__To__INTEGER_128_LittleEndian(
                                                    SectorID,
                                                    blockID128
                                                   );

                // Start an XTS session
                if ((errnum = xts_start(
                                        cipher, 
                                        Key, 
                                        &(Key[keySizeUnderlying/8]),
                                        (keySizeUnderlying/8), 
                                        0, 
                                        xts
                                       )) != CRYPT_OK)
                    {
                    status = STATUS_UNSUCCESSFUL;
                    DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start XTS session (errnum: %d)\n"), errnum));
                    }
                else
                    {
                    if (encryptNotDecrypt)
                        {
                        if ((errnum = xts_encrypt(
                                                  InData, 
                                                  InLength, 
                                                  OutData, 
                                                  blockID128,
                                                  xts
                                                 )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }
                    else 
                        {
                        if ((errnum = xts_decrypt(
                                              InData, 
                                              InLength, 
                                              OutData, 
                                              blockID128,
                                              xts
                                             )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }

                    xts_done(xts);
                    }

                SecZeroMemory(xts, sizeof(symmetric_xts));
                FREEOTFE_FREE(xts);

                break;
                }

            }

        }

    DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherDecryptData\n")));

    return status;
}