in lsvmtool/lsvmtoolmain.c [584:790]
static int _crypt_command(int argc, const char** argv, int encrypt)
{
int rc = 0;
const char* arg0;
unsigned char* key = NULL;
size_t keyBytes = 0;
const char* infile;
const char* outfile;
unsigned char* in = NULL;
unsigned char* out = NULL;
size_t inSize;
unsigned long outSize = 0;
const char* keyfile = NULL;
/* Extract the --keyfile option (if any) */
if ((rc = GetOpt(&argc, argv, "--keyfile", &keyfile)) < 0)
{
fprintf(stderr, "%s: missing option argument: --keyfile\n", argv[0]);
rc = -1;
goto done;
}
rc = 0;
/* Check usage */
if (argc != 3)
{
fprintf(stderr, "Usage: %s [OPTIONS] INFILE OUTFILE\n", argv[0]);
rc = -1;
goto done;
}
/* Collect arguments */
arg0 = argv[0];
infile = argv[1];
outfile = argv[2];
/* Load the key */
if (keyfile)
{
if (LoadFile(keyfile, 0, &key, &keyBytes) != 0)
{
fprintf(stderr, "%s: failed to read %s\n", argv[0], keyfile);
rc = -1;
goto done;
}
const UINT32 KEYSIZE = 32;
if (keyBytes != KEYSIZE)
{
fprintf(stderr, "%s: bootkey must be %u bytes\n", argv[0],
(unsigned int)(KEYSIZE));
rc = -1;
goto done;
}
}
/* If no key yet, then ask for passphrase interactively */
if (!key)
{
char passphrase[_SC_PASS_MAX] = { '\0' };
SHA256Hash sha256;
/* Ask for a passphrase */
{
char* pw;
if (!(pw = getpass("passphrase: ")))
{
fprintf(stderr, "%s: failed to get passphrase\n", argv[0]);
rc = -1;
goto done;
}
if (Strlcpy(passphrase, pw, _SC_PASS_MAX) >= _SC_PASS_MAX)
{
fprintf(stderr, "%s: passphrase is too long\n", argv[0]);
rc = -1;
goto done;
}
}
if (!ComputeSHA256(passphrase, strlen(passphrase), &sha256))
{
fprintf(stderr, "%s: failed to compute SHA-256 of passphrase\n",
argv[0]);
rc = -1;
goto done;
}
if (!(key = (unsigned char*)malloc(sizeof(SHA256Hash))))
{
fprintf(stderr, "%s: out of memory\n", argv[0]);
rc = -1;
goto done;
}
memcpy(key, sha256.buf, sizeof(SHA256Hash));
keyBytes = sizeof(SHA256Hash);
}
/* Load the input file into memory */
if (LoadFile(infile, 0, &in, &inSize) != 0)
{
fprintf(stderr, "%s: cannot load '%s'\n", arg0, infile);
rc = -1;
goto done;
}
if (encrypt)
{
/* Encrypt the data */
if (TPM2X_AES_CBC_Encrypt(
in,
inSize,
key,
keyBytes * 8,
&out,
&outSize) != 0)
{
fprintf(stderr, "%s: TPM2X_AES_CBC_Encrypt() failed\n", arg0);
rc = -1;
goto done;
}
}
else
{
/* Get the initialization vector */
unsigned char iv[AES_BLOCK_SIZE];
const unsigned int ivSize = sizeof(iv);
const unsigned char* data;
unsigned long size;
if (inSize < AES_BLOCK_SIZE + sizeof(ULONG))
{
fprintf(stderr, "%s: not enough data\n", arg0);
rc = -1;
goto done;
}
data = in;
size = inSize;
/* Extract [IV] */
memcpy(iv, data, AES_BLOCK_SIZE);
data += AES_BLOCK_SIZE;
size -= AES_BLOCK_SIZE;
/* Extract [ULONG] */
ULONG tmp;
memcpy(&tmp, data, sizeof(ULONG));
data += sizeof(ULONG);
size -= sizeof(ULONG);
/* Decrypt the data */
if ((rc = TPM2X_AES_CBC_Decrypt(
data,
size,
key,
keyBytes * 8, /* keyBits */
iv,
ivSize,
&out,
&outSize)) != 0)
{
fprintf(stderr, "%s: TPM2X_AES_CBC_Decrypt(): %d \n", arg0, rc);
rc = -1;
goto done;
}
}
/* Write the output file */
{
FILE* os;
if ((os = fopen(outfile, "wb")) == NULL)
{
fprintf(stderr, "%s: failed to open: '%s'\n", arg0, outfile);
rc = -1;
goto done;
}
if (fwrite(out, 1, outSize, os) != outSize)
{
fprintf(stderr, "%s: failed to write: '%s'\n", arg0, outfile);
fclose(os);
rc = -1;
goto done;
}
fclose(os);
}
done:
if (key)
free(key);
if (in)
free(in);
if (out)
free(out);
return rc;
}