зеркало из https://github.com/microsoft/lsvmtools.git
288 строки
5.9 KiB
C
288 строки
5.9 KiB
C
/*
|
|
**==============================================================================
|
|
**
|
|
** LSVMTools
|
|
**
|
|
** MIT License
|
|
**
|
|
** Copyright (c) Microsoft Corporation. All rights reserved.
|
|
**
|
|
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
** of this software and associated documentation files (the "Software"), to deal
|
|
** in the Software without restriction, including without limitation the rights
|
|
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
** copies of the Software, and to permit persons to whom the Software is
|
|
** furnished to do so, subject to the following conditions:
|
|
**
|
|
** The above copyright notice and this permission notice shall be included in
|
|
** all copies or substantial portions of the Software.
|
|
**
|
|
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
** SOFTWARE
|
|
**
|
|
**==============================================================================
|
|
*/
|
|
#if defined (_WIN32)
|
|
# define WIN32_NO_STATUS
|
|
# include <Windows.h>
|
|
# undef WIN32_NO_STATUS
|
|
# include <bcrypt.h>
|
|
# include <ntstatus.h>
|
|
# include <intrin.h>
|
|
# include "bcryptdefines.h"
|
|
#endif
|
|
|
|
#include "../crypto/utils_crypto.h"
|
|
#include "strings.h"
|
|
#include "luks.h"
|
|
#include "alloc.h"
|
|
#include "print.h"
|
|
|
|
void LUKSInitialize()
|
|
{
|
|
}
|
|
|
|
void LUKSShutdown()
|
|
{
|
|
}
|
|
|
|
struct _LUKSCipher
|
|
{
|
|
crypto_cipher *cipher;
|
|
UINT8* key;
|
|
UINTN keySize;
|
|
};
|
|
|
|
LUKSCipher* LUKSGetAES256ECBCipher(
|
|
const UINT8* key,
|
|
UINTN keySize)
|
|
{
|
|
LUKSCipher tmp;
|
|
LUKSCipher* result = NULL;
|
|
|
|
Memset(&tmp, 0xDD, sizeof(tmp));
|
|
|
|
/* Create crypto_cipher object */
|
|
if (CryptoCipherInit(
|
|
CRYPTO_AES_CBC,
|
|
(UINT8*)key,
|
|
keySize,
|
|
&tmp.cipher) != CRYPTO_ERR_NONE)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
/* Copy the key */
|
|
{
|
|
if (!(tmp.key = (UINT8*)Malloc(keySize)))
|
|
goto done;
|
|
|
|
Memcpy(tmp.key, key, keySize);
|
|
tmp.keySize = keySize;
|
|
}
|
|
|
|
/* Create and initialize object */
|
|
{
|
|
if (!(result = (LUKSCipher*)Calloc(1, sizeof(LUKSCipher))))
|
|
goto done;
|
|
|
|
Memcpy(result, &tmp, sizeof(LUKSCipher));
|
|
}
|
|
|
|
done:
|
|
|
|
if (!result)
|
|
{
|
|
if (tmp.key)
|
|
Free(tmp.key);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
LUKSCipher* LUKSGetCipher(
|
|
const LUKSHeader* header,
|
|
const UINT8* key,
|
|
UINTN keySize)
|
|
{
|
|
LUKSCipher tmp;
|
|
LUKSCipher* result = NULL;
|
|
crypto_algo algo;
|
|
UINT32 keyBits;
|
|
|
|
Memset(&tmp, 0xDD, sizeof(tmp));
|
|
|
|
/* Check for null parameters */
|
|
if (!header)
|
|
goto done;
|
|
|
|
/* Create crypto_cipher object */
|
|
{
|
|
/* Only supporting AES cipher for now */
|
|
if (Strcmp(header->cipher_name, "aes") != 0)
|
|
goto done;
|
|
|
|
/* Set the key length in bits */
|
|
keyBits = header->key_bytes * 8;
|
|
|
|
/* Determine the cipher mode */
|
|
if (Strcmp(header->cipher_mode, "cbc-plain") == 0)
|
|
algo = CRYPTO_AES_CBC;
|
|
else if (Strcmp(header->cipher_mode, "cbc-essiv:") == 0)
|
|
algo = CRYPTO_AES_CBC;
|
|
else if (Strcmp(header->cipher_mode, "xts-plain64") == 0)
|
|
{
|
|
algo = CRYPTO_AES_XTS;
|
|
keyBits /= 2;
|
|
}
|
|
else
|
|
goto done;
|
|
|
|
if (CryptoCipherInit(
|
|
algo,
|
|
(UINT8*)key,
|
|
keySize,
|
|
&tmp.cipher) != CRYPTO_ERR_NONE)
|
|
{
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Copy the key */
|
|
{
|
|
if (!(tmp.key = (UINT8*)Malloc(keySize)))
|
|
goto done;
|
|
|
|
Memcpy(tmp.key, key, keySize);
|
|
tmp.keySize = keySize;
|
|
}
|
|
|
|
/* Create and initialize object */
|
|
{
|
|
if (!(result = (LUKSCipher*)Calloc(1, sizeof(LUKSCipher))))
|
|
goto done;
|
|
|
|
Memcpy(result, &tmp, sizeof(LUKSCipher));
|
|
}
|
|
|
|
done:
|
|
|
|
if (!result)
|
|
{
|
|
if (tmp.key)
|
|
Free(tmp.key);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void LUKSReleaseCipher(
|
|
LUKSCipher* cipher)
|
|
{
|
|
if (!cipher)
|
|
return;
|
|
|
|
if (cipher->key)
|
|
Free(cipher->key);
|
|
|
|
Free(cipher);
|
|
}
|
|
|
|
int LUKSCryptData(
|
|
LUKSCipher* cipher,
|
|
LUKSCryptMode mode,
|
|
UINT8 *iv,
|
|
UINTN ivSize,
|
|
const UINT8 *in,
|
|
UINTN inSize,
|
|
UINT8 *out_)
|
|
{
|
|
int rc = -1;
|
|
|
|
/* Check parameters */
|
|
if (!cipher || !iv || !in || !out_)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
/* Encrypt/Decrypt data */
|
|
if (mode)
|
|
{
|
|
if (CryptoCipherEncryptNoPad(
|
|
cipher->cipher,
|
|
(UINT8*)in,
|
|
inSize,
|
|
iv,
|
|
ivSize,
|
|
out_,
|
|
inSize) != CRYPTO_ERR_NONE)
|
|
{
|
|
goto done;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CryptoCipherDecryptNoPad(
|
|
cipher->cipher,
|
|
(UINT8*)in,
|
|
inSize,
|
|
iv,
|
|
ivSize,
|
|
out_,
|
|
inSize) != CRYPTO_ERR_NONE)
|
|
{
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
rc = 0;
|
|
|
|
done:
|
|
|
|
return rc;
|
|
}
|
|
|
|
int LUKSDeriveKey(
|
|
const char *pass,
|
|
int passlen,
|
|
const unsigned char* salt,
|
|
int saltlen,
|
|
int iter,
|
|
const char* hashspec,
|
|
int keylen,
|
|
unsigned char* out)
|
|
{
|
|
int rc = -1;
|
|
crypto_algo algo;
|
|
|
|
if (Strcmp(hashspec, "sha1") == 0)
|
|
algo = CRYPTO_HMAC_SHA1;
|
|
else if (Strcmp(hashspec, "sha256") == 0)
|
|
algo = CRYPTO_HMAC_SHA256;
|
|
else
|
|
goto done;
|
|
|
|
if (CryptoPBKDF2(
|
|
algo,
|
|
(UINT8*)pass,
|
|
passlen,
|
|
(UINT8*)salt,
|
|
saltlen,
|
|
iter,
|
|
out,
|
|
keylen) != CRYPTO_ERR_NONE)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
rc = 0;
|
|
|
|
done:
|
|
return rc;
|
|
}
|