static int _crypt_command()

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;
}