summaryrefslogtreecommitdiff
path: root/src/trspi/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/trspi/crypto')
-rw-r--r--src/trspi/crypto/Makefile.am1
-rw-r--r--src/trspi/crypto/openssl/hash.c218
-rw-r--r--src/trspi/crypto/openssl/rsa.c266
-rw-r--r--src/trspi/crypto/openssl/symmetric.c388
4 files changed, 873 insertions, 0 deletions
diff --git a/src/trspi/crypto/Makefile.am b/src/trspi/crypto/Makefile.am
new file mode 100644
index 0000000..bc3bf86
--- /dev/null
+++ b/src/trspi/crypto/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = openssl
diff --git a/src/trspi/crypto/openssl/hash.c b/src/trspi/crypto/openssl/hash.c
new file mode 100644
index 0000000..f6cf3dc
--- /dev/null
+++ b/src/trspi/crypto/openssl/hash.c
@@ -0,0 +1,218 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2004-2006
+ *
+ */
+
+/*
+ * hash.c - openssl TSS crypto routines
+ *
+ * Kent Yoder <shpedoikal@gmail.com>
+ *
+ */
+
+#include <string.h>
+
+#include <openssl/opensslv.h>
+#include <openssl/rsa.h> // for some reason the MGF1 prototype is in here
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/err.h>
+#include <openssl/sha.h>
+
+#include "trousers/tss.h"
+#include "trousers/trousers.h"
+#include "trousers_types.h"
+#include "spi_utils.h"
+#include "tsplog.h"
+
+#ifdef TSS_DEBUG
+#define DEBUG_print_openssl_errors() \
+ do { \
+ ERR_load_crypto_strings(); \
+ ERR_print_errors_fp(stderr); \
+ } while (0)
+#else
+#define DEBUG_print_openssl_errors()
+#endif
+
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
+#define OpenSSL_MGF1(m,mlen,s,slen,md) PKCS1_MGF1(m,mlen,s,slen,md)
+#else
+int MGF1(unsigned char *, long, const unsigned char *, long);
+#define OpenSSL_MGF1(m,mlen,s,slen,md) MGF1(m,mlen,s,slen)
+#endif
+
+/*
+ * Hopefully this will make the code clearer since
+ * OpenSSL returns 1 on success
+ */
+#define EVP_SUCCESS 1
+
+TSS_RESULT
+Trspi_Hash(UINT32 HashType, UINT32 BufSize, BYTE* Buf, BYTE* Digest)
+{
+ EVP_MD_CTX md_ctx;
+ unsigned int result_size;
+ int rv;
+
+ switch (HashType) {
+ case TSS_HASH_SHA1:
+ rv = EVP_DigestInit(&md_ctx, EVP_sha1());
+ break;
+ default:
+ rv = TSPERR(TSS_E_BAD_PARAMETER);
+ goto out;
+ break;
+ }
+
+ if (rv != EVP_SUCCESS) {
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto err;
+ }
+
+ rv = EVP_DigestUpdate(&md_ctx, Buf, BufSize);
+ if (rv != EVP_SUCCESS) {
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto err;
+ }
+
+ result_size = EVP_MD_CTX_size(&md_ctx);
+ rv = EVP_DigestFinal(&md_ctx, Digest, &result_size);
+ if (rv != EVP_SUCCESS) {
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto err;
+ } else
+ rv = TSS_SUCCESS;
+
+ goto out;
+
+err:
+ DEBUG_print_openssl_errors();
+out:
+ return rv;
+}
+
+TSS_RESULT
+Trspi_HashInit(Trspi_HashCtx *ctx, UINT32 HashType)
+{
+ int rv;
+ EVP_MD *md;
+
+ switch (HashType) {
+ case TSS_HASH_SHA1:
+ md = (EVP_MD *)EVP_sha1();
+ break;
+ default:
+ return TSPERR(TSS_E_BAD_PARAMETER);
+ break;
+ }
+
+ if ((ctx->ctx = malloc(sizeof(EVP_MD_CTX))) == NULL)
+ return TSPERR(TSS_E_OUTOFMEMORY);
+
+ rv = EVP_DigestInit((EVP_MD_CTX *)ctx->ctx, (const EVP_MD *)md);
+
+ if (rv != EVP_SUCCESS) {
+ DEBUG_print_openssl_errors();
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+Trspi_HashUpdate(Trspi_HashCtx *ctx, UINT32 size, BYTE *data)
+{
+ int rv;
+
+ if (ctx == NULL || ctx->ctx == NULL)
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+
+ if (data == NULL && size)
+ return TSPERR(TSS_E_BAD_PARAMETER);
+
+ if (!size)
+ return TSS_SUCCESS;
+
+ rv = EVP_DigestUpdate(ctx->ctx, data, size);
+ if (rv != EVP_SUCCESS) {
+ DEBUG_print_openssl_errors();
+ free(ctx->ctx);
+ ctx->ctx = NULL;
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+ }
+
+ return TSS_SUCCESS;
+}
+
+TSS_RESULT
+Trspi_HashFinal(Trspi_HashCtx *ctx, BYTE *digest)
+{
+ int rv;
+ UINT32 result_size;
+
+ if (ctx == NULL || ctx->ctx == NULL)
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+
+ result_size = EVP_MD_CTX_size((EVP_MD_CTX *)ctx->ctx);
+ rv = EVP_DigestFinal(ctx->ctx, digest, &result_size);
+ if (rv != EVP_SUCCESS)
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+
+ free(ctx->ctx);
+ ctx->ctx = NULL;
+
+ return TSS_SUCCESS;
+}
+
+UINT32
+Trspi_HMAC(UINT32 HashType, UINT32 SecretSize, BYTE* Secret, UINT32 BufSize, BYTE* Buf, BYTE* hmacOut)
+{
+ /*HMAC_CTX hmac_ctx;*/
+ const EVP_MD *md;
+ unsigned int len;
+ int rv = TSS_SUCCESS;
+
+ switch (HashType) {
+ case TSS_HASH_SHA1:
+ md = EVP_sha1();
+ break;
+ default:
+ rv = TSPERR(TSS_E_BAD_PARAMETER);
+ goto out;
+ break;
+ }
+
+ len = EVP_MD_size(md);
+
+ HMAC(md, Secret, SecretSize, Buf, BufSize, hmacOut, &len);
+out:
+ return rv;
+}
+
+TSS_RESULT
+Trspi_MGF1(UINT32 alg, UINT32 seedLen, BYTE *seed, UINT32 outLen, BYTE *out)
+{
+ const EVP_MD *md;
+ long olen = outLen, slen = seedLen;
+ int rv = TSS_SUCCESS;
+
+ switch (alg) {
+ case TSS_HASH_SHA1:
+ md = EVP_sha1();
+ break;
+ default:
+ rv = TSPERR(TSS_E_BAD_PARAMETER);
+ goto out;
+ break;
+ }
+
+ rv = OpenSSL_MGF1(out, olen, seed, slen, md);
+out:
+ return rv;
+}
diff --git a/src/trspi/crypto/openssl/rsa.c b/src/trspi/crypto/openssl/rsa.c
new file mode 100644
index 0000000..0bd1e89
--- /dev/null
+++ b/src/trspi/crypto/openssl/rsa.c
@@ -0,0 +1,266 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2004-2006
+ *
+ */
+
+/*
+ * rsa.c - openssl TSS crypto routines
+ *
+ * Kent Yoder <shpedoikal@gmail.com>
+ *
+ */
+
+#include <string.h>
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/sha.h>
+#include <openssl/rsa.h>
+
+#include "trousers/tss.h"
+#include "trousers/trousers.h"
+#include "trousers_types.h"
+#include "spi_utils.h"
+#include "tsplog.h"
+
+#ifdef TSS_DEBUG
+#define DEBUG_print_openssl_errors() \
+ do { \
+ ERR_load_crypto_strings(); \
+ ERR_print_errors_fp(stderr); \
+ } while (0)
+#else
+#define DEBUG_print_openssl_errors()
+#endif
+
+
+/*
+ * Hopefully this will make the code clearer since
+ * OpenSSL returns 1 on success
+ */
+#define EVP_SUCCESS 1
+
+/* XXX int set to unsigned int values */
+int
+Trspi_RSA_Encrypt(unsigned char *dataToEncrypt, /* in */
+ unsigned int dataToEncryptLen, /* in */
+ unsigned char *encryptedData, /* out */
+ unsigned int *encryptedDataLen, /* out */
+ unsigned char *publicKey,
+ unsigned int keysize)
+{
+ int rv;
+ unsigned char exp[] = { 0x01, 0x00, 0x01 }; /* 65537 hex */
+ unsigned char oaepPad[] = "TCPA";
+ int oaepPadLen = 4;
+ RSA *rsa = RSA_new();
+ BYTE encodedData[256];
+ int encodedDataLen;
+
+ if (rsa == NULL) {
+ rv = TSPERR(TSS_E_OUTOFMEMORY);
+ goto err;
+ }
+
+ /* set the public key value in the OpenSSL object */
+ rsa->n = BN_bin2bn(publicKey, keysize, rsa->n);
+ /* set the public exponent */
+ rsa->e = BN_bin2bn(exp, sizeof(exp), rsa->e);
+
+ if (rsa->n == NULL || rsa->e == NULL) {
+ rv = TSPERR(TSS_E_OUTOFMEMORY);
+ goto err;
+ }
+
+ /* padding constraint for PKCS#1 OAEP padding */
+ if ((int)dataToEncryptLen >= (RSA_size(rsa) - ((2 * SHA_DIGEST_LENGTH) + 1))) {
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto err;
+ }
+
+ encodedDataLen = MIN(RSA_size(rsa), 256);
+
+ /* perform our OAEP padding here with custom padding parameter */
+ rv = RSA_padding_add_PKCS1_OAEP(encodedData, encodedDataLen, dataToEncrypt,
+ dataToEncryptLen, oaepPad, oaepPadLen);
+ if (rv != EVP_SUCCESS) {
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* call OpenSSL with no additional padding */
+ rv = RSA_public_encrypt(encodedDataLen, encodedData,
+ encryptedData, rsa, RSA_NO_PADDING);
+ if (rv == -1) {
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* RSA_public_encrypt returns the size of the encrypted data */
+ *encryptedDataLen = rv;
+ rv = TSS_SUCCESS;
+ goto out;
+
+err:
+ DEBUG_print_openssl_errors();
+out:
+ if (rsa)
+ RSA_free(rsa);
+ return rv;
+}
+
+TSS_RESULT
+Trspi_Verify(UINT32 HashType, BYTE *pHash, UINT32 iHashLength,
+ unsigned char *pModulus, int iKeyLength,
+ BYTE *pSignature, UINT32 sig_len)
+{
+ int rv, nid;
+ unsigned char exp[] = { 0x01, 0x00, 0x01 }; /* The default public exponent for the TPM */
+ unsigned char buf[256];
+ RSA *rsa = RSA_new();
+
+ if (rsa == NULL) {
+ rv = TSPERR(TSS_E_OUTOFMEMORY);
+ goto err;
+ }
+
+ /* We assume we're verifying data from a TPM, so there are only
+ * two options, SHA1 data and PKCSv1.5 encoded signature data.
+ */
+ switch (HashType) {
+ case TSS_HASH_SHA1:
+ nid = NID_sha1;
+ break;
+ case TSS_HASH_OTHER:
+ nid = NID_undef;
+ break;
+ default:
+ rv = TSPERR(TSS_E_BAD_PARAMETER);
+ goto out;
+ break;
+ }
+
+ /* set the public key value in the OpenSSL object */
+ rsa->n = BN_bin2bn(pModulus, iKeyLength, rsa->n);
+ /* set the public exponent */
+ rsa->e = BN_bin2bn(exp, sizeof(exp), rsa->e);
+
+ if (rsa->n == NULL || rsa->e == NULL) {
+ rv = TSPERR(TSS_E_OUTOFMEMORY);
+ goto err;
+ }
+
+ /* if we don't know the structure of the data we're verifying, do a public decrypt
+ * and compare manually. If we know we're looking for a SHA1 hash, allow OpenSSL
+ * to do the work for us.
+ */
+ if (nid == NID_undef) {
+ rv = RSA_public_decrypt(sig_len, pSignature, buf, rsa, RSA_PKCS1_PADDING);
+ if ((UINT32)rv != iHashLength) {
+ rv = TSPERR(TSS_E_FAIL);
+ goto out;
+ } else if (memcmp(pHash, buf, iHashLength)) {
+ rv = TSPERR(TSS_E_FAIL);
+ goto out;
+ }
+ } else {
+ if ((rv = RSA_verify(nid, pHash, iHashLength, pSignature, sig_len, rsa)) == 0) {
+ rv = TSPERR(TSS_E_FAIL);
+ goto out;
+ }
+ }
+
+ rv = TSS_SUCCESS;
+ goto out;
+
+err:
+ DEBUG_print_openssl_errors();
+out:
+ if (rsa)
+ RSA_free(rsa);
+ return rv;
+}
+
+int
+Trspi_RSA_Public_Encrypt(unsigned char *in, unsigned int inlen,
+ unsigned char *out, unsigned int *outlen,
+ unsigned char *pubkey, unsigned int pubsize,
+ unsigned int e, int padding)
+{
+ int rv, e_size = 3;
+ unsigned char exp[] = { 0x01, 0x00, 0x01 };
+ RSA *rsa = RSA_new();
+
+ if (rsa == NULL) {
+ rv = TSPERR(TSS_E_OUTOFMEMORY);
+ goto err;
+ }
+
+ switch (e) {
+ case 0:
+ /* fall through */
+ case 65537:
+ break;
+ case 17:
+ exp[0] = 17;
+ e_size = 1;
+ break;
+ case 3:
+ exp[0] = 3;
+ e_size = 1;
+ break;
+ default:
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto out;
+ break;
+ }
+
+ switch (padding) {
+ case TR_RSA_PKCS1_OAEP_PADDING:
+ padding = RSA_PKCS1_OAEP_PADDING;
+ break;
+ case TR_RSA_PKCS1_PADDING:
+ padding = RSA_PKCS1_PADDING;
+ break;
+ case TR_RSA_NO_PADDING:
+ padding = RSA_NO_PADDING;
+ break;
+ default:
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto out;
+ break;
+ }
+
+ /* set the public key value in the OpenSSL object */
+ rsa->n = BN_bin2bn(pubkey, pubsize, rsa->n);
+ /* set the public exponent */
+ rsa->e = BN_bin2bn(exp, e_size, rsa->e);
+
+ if (rsa->n == NULL || rsa->e == NULL) {
+ rv = TSPERR(TSS_E_OUTOFMEMORY);
+ goto err;
+ }
+
+ rv = RSA_public_encrypt(inlen, in, out, rsa, padding);
+ if (rv == -1) {
+ rv = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* RSA_public_encrypt returns the size of the encrypted data */
+ *outlen = rv;
+ rv = TSS_SUCCESS;
+ goto out;
+
+err:
+ DEBUG_print_openssl_errors();
+out:
+ if (rsa)
+ RSA_free(rsa);
+ return rv;
+}
diff --git a/src/trspi/crypto/openssl/symmetric.c b/src/trspi/crypto/openssl/symmetric.c
new file mode 100644
index 0000000..f5c3836
--- /dev/null
+++ b/src/trspi/crypto/openssl/symmetric.c
@@ -0,0 +1,388 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2004-2006
+ *
+ */
+
+/*
+ * symmetric.c - openssl TSS crypto routines
+ *
+ * Kent Yoder <shpedoikal@gmail.com>
+ *
+ */
+
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <limits.h>
+
+#include "trousers/tss.h"
+#include "trousers/trousers.h"
+#include "trousers_types.h"
+#include "spi_utils.h"
+#include "tsplog.h"
+
+
+#ifdef TSS_DEBUG
+#define DEBUG_print_openssl_errors() \
+ do { \
+ ERR_load_crypto_strings(); \
+ ERR_print_errors_fp(stderr); \
+ } while (0)
+#else
+#define DEBUG_print_openssl_errors()
+#endif
+
+
+/*
+ * Hopefully this will make the code clearer since
+ * OpenSSL returns 1 on success
+ */
+#define EVP_SUCCESS 1
+
+TSS_RESULT
+Trspi_Encrypt_ECB(UINT16 alg, BYTE *key, BYTE *in, UINT32 in_len, BYTE *out,
+ UINT32 *out_len)
+{
+ TSS_RESULT result = TSS_SUCCESS;
+ EVP_CIPHER_CTX ctx;
+ UINT32 tmp;
+
+ switch (alg) {
+ case TSS_ALG_AES:
+ break;
+ default:
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ break;
+ }
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ if (!EVP_EncryptInit(&ctx, EVP_aes_256_ecb(), key, NULL)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ if (*out_len < in_len + EVP_CIPHER_CTX_block_size(&ctx) - 1) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ if (!EVP_EncryptUpdate(&ctx, out, (int *)out_len, in, in_len)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ if (!EVP_EncryptFinal(&ctx, out + *out_len, (int *)&tmp)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+ *out_len += tmp;
+done:
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return result;
+}
+
+TSS_RESULT
+Trspi_Decrypt_ECB(UINT16 alg, BYTE *key, BYTE *in, UINT32 in_len, BYTE *out,
+ UINT32 *out_len)
+{
+ TSS_RESULT result = TSS_SUCCESS;
+ EVP_CIPHER_CTX ctx;
+ UINT32 tmp;
+
+ switch (alg) {
+ case TSS_ALG_AES:
+ break;
+ default:
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ break;
+ }
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ if (!EVP_DecryptInit(&ctx, EVP_aes_256_ecb(), key, NULL)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ if (!EVP_DecryptUpdate(&ctx, out, (int *)out_len, in, in_len)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ if (!EVP_DecryptFinal(&ctx, out + *out_len, (int *)&tmp)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+ *out_len += tmp;
+done:
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return result;
+}
+
+EVP_CIPHER *
+get_openssl_cipher(UINT16 alg, UINT16 mode)
+{
+ EVP_CIPHER *cipher = NULL;
+
+ switch (alg) {
+ case TSS_ALG_AES:
+ case TCPA_ALG_AES:
+ switch (mode) {
+ case TPM_ES_NONE:
+ case TSS_ES_NONE:
+ case TPM_ES_SYM_CBC_PKCS5PAD:
+ LogDebug("XXX Make sure this is really PKCS5 padded");
+ case TR_SYM_MODE_CBC:
+ cipher = (EVP_CIPHER *)EVP_aes_128_cbc();
+ break;
+ case TPM_ES_SYM_OFB:
+ cipher = (EVP_CIPHER *)EVP_aes_128_ofb();
+ break;
+ case TPM_ES_SYM_CNT:
+ LogDebug("XXX AES128 in CTR mode unsupp by openssl EVP");
+ default:
+ LogDebug("Invalid mode in doing symmetric encryption");
+ break;
+ }
+ break;
+ case TSS_ALG_DES:
+ case TCPA_ALG_DES:
+ switch (mode) {
+ case TPM_ES_NONE:
+ case TSS_ES_NONE:
+ case TPM_ES_SYM_CBC_PKCS5PAD:
+ LogDebug("XXX Make sure this is really PKCS5 padded");
+ case TR_SYM_MODE_CBC:
+ cipher = (EVP_CIPHER *)EVP_des_cbc();
+ break;
+ case TPM_ES_SYM_OFB:
+ cipher = (EVP_CIPHER *)EVP_des_ofb();
+ break;
+ case TPM_ES_SYM_CNT:
+ LogDebug("XXX DES in CTR mode unsupp by openssl EVP");
+ default:
+ LogDebug("Invalid mode in doing symmetric encryption");
+ break;
+ }
+ break;
+ case TSS_ALG_3DES:
+ case TCPA_ALG_3DES:
+ switch (mode) {
+ case TPM_ES_NONE:
+ case TSS_ES_NONE:
+ case TPM_ES_SYM_CBC_PKCS5PAD:
+ LogDebug("XXX Make sure this is really PKCS5 padded");
+ case TR_SYM_MODE_CBC:
+ cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
+ break;
+ case TPM_ES_SYM_OFB:
+ cipher = (EVP_CIPHER *)EVP_des_ede3_ofb();
+ break;
+ case TPM_ES_SYM_CNT:
+ LogDebug("XXX 3DES in CTR mode unsupp by openssl EVP");
+ default:
+ LogDebug("Invalid mode in doing symmetric encryption");
+ break;
+ }
+ break;
+ case TPM_ALG_AES192:
+ case TSS_ALG_AES192:
+ switch (mode) {
+ case TPM_ES_NONE:
+ case TSS_ES_NONE:
+ case TPM_ES_SYM_CBC_PKCS5PAD:
+ LogDebug("XXX Make sure this is really PKCS5 padded");
+ case TR_SYM_MODE_CBC:
+ cipher = (EVP_CIPHER *)EVP_aes_192_cbc();
+ break;
+ case TPM_ES_SYM_OFB:
+ cipher = (EVP_CIPHER *)EVP_aes_192_ofb();
+ break;
+ case TPM_ES_SYM_CNT:
+ LogDebug("XXX AES192 in CTR mode unsupp by openssl EVP");
+ default:
+ LogDebug("Invalid mode in doing symmetric encryption");
+ break;
+ }
+ break;
+ case TPM_ALG_AES256:
+ case TSS_ALG_AES256:
+ switch (mode) {
+ case TPM_ES_NONE:
+ case TSS_ES_NONE:
+ case TPM_ES_SYM_CBC_PKCS5PAD:
+ LogDebug("XXX Make sure this is really PKCS5 padded");
+ case TR_SYM_MODE_CBC:
+ cipher = (EVP_CIPHER *)EVP_aes_256_cbc();
+ break;
+ case TPM_ES_SYM_OFB:
+ cipher = (EVP_CIPHER *)EVP_aes_256_ofb();
+ break;
+ case TPM_ES_SYM_CNT:
+ LogDebug("XXX AES256 in CTR mode unsupp by openssl EVP");
+ default:
+ LogDebug("Invalid mode in doing symmetric encryption");
+ break;
+ }
+ break;
+ default:
+ LogDebug("Invalid algorithm in doing symmetric encryption");
+ break;
+ }
+
+ return cipher;
+}
+
+TSS_RESULT
+Trspi_SymEncrypt(UINT16 alg, UINT16 mode, BYTE *key, BYTE *iv, BYTE *in, UINT32 in_len, BYTE *out,
+ UINT32 *out_len)
+{
+ TSS_RESULT result = TSS_SUCCESS;
+ EVP_CIPHER_CTX ctx;
+ EVP_CIPHER *cipher;
+ BYTE *def_iv = NULL, *outiv_ptr;
+ UINT32 tmp;
+ int iv_len, outiv_len;
+
+ if (*out_len > INT_MAX)
+ outiv_len = INT_MAX;
+ else
+ outiv_len = *(int *)out_len;
+
+ if ((cipher = get_openssl_cipher(alg, mode)) == NULL)
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ /* If the iv passed in is NULL, create a new random iv and prepend it to the ciphertext */
+ iv_len = EVP_CIPHER_iv_length(cipher);
+ if (iv == NULL) {
+ def_iv = malloc(iv_len);
+ if (def_iv == NULL) {
+ LogError("malloc of %d bytes failed.", iv_len);
+ return TSPERR(TSS_E_OUTOFMEMORY);
+ }
+ RAND_bytes(def_iv, iv_len);
+
+ memcpy(out, def_iv, iv_len);
+ outiv_ptr = &out[iv_len];
+ outiv_len -= iv_len;
+ } else {
+ def_iv = iv;
+ outiv_ptr = out;
+ }
+
+ if (!EVP_EncryptInit(&ctx, (const EVP_CIPHER *)cipher, key, def_iv)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ if ((UINT32)outiv_len < in_len + (EVP_CIPHER_CTX_block_size(&ctx) * 2) - 1) {
+ LogDebug("Not enough space to do symmetric encryption");
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ goto done;
+ }
+
+ if (!EVP_EncryptUpdate(&ctx, outiv_ptr, &outiv_len, in, in_len)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ if (!EVP_EncryptFinal(&ctx, outiv_ptr + outiv_len, (int *)&tmp)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ outiv_len += tmp;
+ *out_len = outiv_len;
+done:
+ if (def_iv != iv) {
+ *out_len += iv_len;
+ free(def_iv);
+ }
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return result;
+}
+
+TSS_RESULT
+Trspi_SymDecrypt(UINT16 alg, UINT16 mode, BYTE *key, BYTE *iv, BYTE *in, UINT32 in_len, BYTE *out,
+ UINT32 *out_len)
+{
+ TSS_RESULT result = TSS_SUCCESS;
+ EVP_CIPHER_CTX ctx;
+ EVP_CIPHER *cipher;
+ BYTE *def_iv = NULL, *iniv_ptr;
+ UINT32 tmp;
+ int iv_len, iniv_len;
+
+ if (in_len > INT_MAX)
+ return TSS_E_BAD_PARAMETER;
+
+ if ((cipher = get_openssl_cipher(alg, mode)) == NULL)
+ return TSPERR(TSS_E_INTERNAL_ERROR);
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ /* If the iv is NULL, assume that its prepended to the ciphertext */
+ if (iv == NULL) {
+ iv_len = EVP_CIPHER_iv_length(cipher);
+ def_iv = malloc(iv_len);
+ if (def_iv == NULL) {
+ LogError("malloc of %d bytes failed.", iv_len);
+ return TSPERR(TSS_E_OUTOFMEMORY);
+ }
+
+ memcpy(def_iv, in, iv_len);
+ iniv_ptr = &in[iv_len];
+ iniv_len = in_len - iv_len;
+ } else {
+ def_iv = iv;
+ iniv_ptr = in;
+ iniv_len = in_len;
+ }
+
+ if (!EVP_DecryptInit(&ctx, cipher, key, def_iv)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ if (!EVP_DecryptUpdate(&ctx, out, (int *)out_len, iniv_ptr, iniv_len)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ if (!EVP_DecryptFinal(&ctx, out + *out_len, (int *)&tmp)) {
+ result = TSPERR(TSS_E_INTERNAL_ERROR);
+ DEBUG_print_openssl_errors();
+ goto done;
+ }
+
+ *out_len += tmp;
+done:
+ if (def_iv != iv)
+ free(def_iv);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return result;
+}