Home | History | Annotate | Line # | Download | only in openssl
      1 
      2 /*
      3  * Licensed Materials - Property of IBM
      4  *
      5  * trousers - An open source TCG Software Stack
      6  *
      7  * (C) Copyright International Business Machines Corp. 2004-2006
      8  *
      9  */
     10 
     11 /*
     12  * symmetric.c - openssl TSS crypto routines
     13  *
     14  * Kent Yoder <shpedoikal (at) gmail.com>
     15  *
     16  */
     17 
     18 #include <limits.h>
     19 #include <string.h>
     20 
     21 #include <openssl/evp.h>
     22 #include <openssl/err.h>
     23 #include <openssl/rand.h>
     24 #include <limits.h>
     25 
     26 #include "trousers/tss.h"
     27 #include "trousers/trousers.h"
     28 #include "trousers_types.h"
     29 #include "spi_utils.h"
     30 #include "tsplog.h"
     31 
     32 
     33 #ifdef TSS_DEBUG
     34 #define DEBUG_print_openssl_errors() \
     35 	do { \
     36 		ERR_load_crypto_strings(); \
     37 		ERR_print_errors_fp(stderr); \
     38 	} while (0)
     39 #else
     40 #define DEBUG_print_openssl_errors()
     41 #endif
     42 
     43 /*
     44  * Hopefully this will make the code clearer since
     45  * OpenSSL returns 1 on success
     46  */
     47 #define EVP_SUCCESS 1
     48 
     49 TSS_RESULT
     50 Trspi_Encrypt_ECB(UINT16 alg, BYTE *key, BYTE *in, UINT32 in_len, BYTE *out,
     51 		  UINT32 *out_len)
     52 {
     53 	TSS_RESULT result = TSS_SUCCESS;
     54 	EVP_CIPHER_CTX *ctx = NULL;
     55 	UINT32 tmp;
     56 
     57 	switch (alg) {
     58 		case TSS_ALG_AES:
     59 			break;
     60 		default:
     61 			result = TSPERR(TSS_E_INTERNAL_ERROR);
     62 			goto done;
     63 			break;
     64 	}
     65 
     66 	ctx = EVP_CIPHER_CTX_new();
     67 
     68 	if (!EVP_EncryptInit(ctx, EVP_aes_256_ecb(), key, NULL)) {
     69 		result = TSPERR(TSS_E_INTERNAL_ERROR);
     70 		DEBUG_print_openssl_errors();
     71 		goto done;
     72 	}
     73 
     74 	if (*out_len < in_len + EVP_CIPHER_CTX_block_size(ctx) - 1) {
     75 		result = TSPERR(TSS_E_INTERNAL_ERROR);
     76 		goto done;
     77 	}
     78 
     79 	if (!EVP_EncryptUpdate(ctx, out, (int *)out_len, in, in_len)) {
     80 		result = TSPERR(TSS_E_INTERNAL_ERROR);
     81 		DEBUG_print_openssl_errors();
     82 		goto done;
     83 	}
     84 
     85 	if (!EVP_EncryptFinal(ctx, out + *out_len, (int *)&tmp)) {
     86 		result = TSPERR(TSS_E_INTERNAL_ERROR);
     87 		DEBUG_print_openssl_errors();
     88 		goto done;
     89 	}
     90 	*out_len += tmp;
     91 done:
     92 	EVP_CIPHER_CTX_free(ctx);
     93 	return result;
     94 }
     95 
     96 TSS_RESULT
     97 Trspi_Decrypt_ECB(UINT16 alg, BYTE *key, BYTE *in, UINT32 in_len, BYTE *out,
     98 		  UINT32 *out_len)
     99 {
    100 	TSS_RESULT result = TSS_SUCCESS;
    101 	EVP_CIPHER_CTX *ctx = NULL;
    102 	UINT32 tmp;
    103 
    104 	switch (alg) {
    105 		case TSS_ALG_AES:
    106 			break;
    107 		default:
    108 			result = TSPERR(TSS_E_INTERNAL_ERROR);
    109 			goto done;
    110 			break;
    111 	}
    112 
    113 	ctx = EVP_CIPHER_CTX_new();
    114 
    115 	if (!EVP_DecryptInit(ctx, EVP_aes_256_ecb(), key, NULL)) {
    116 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    117 		DEBUG_print_openssl_errors();
    118 		goto done;
    119 	}
    120 
    121 	if (!EVP_DecryptUpdate(ctx, out, (int *)out_len, in, in_len)) {
    122 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    123 		DEBUG_print_openssl_errors();
    124 		goto done;
    125 	}
    126 
    127 	if (!EVP_DecryptFinal(ctx, out + *out_len, (int *)&tmp)) {
    128 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    129 		DEBUG_print_openssl_errors();
    130 		goto done;
    131 	}
    132 	*out_len += tmp;
    133 done:
    134 	EVP_CIPHER_CTX_free(ctx);
    135 	return result;
    136 }
    137 
    138 EVP_CIPHER *
    139 get_openssl_cipher(UINT16 alg, UINT16 mode)
    140 {
    141 	EVP_CIPHER *cipher = NULL;
    142 
    143 	switch (alg) {
    144 		case TSS_ALG_AES:
    145 		case TCPA_ALG_AES:
    146 			switch (mode) {
    147 				case TPM_ES_NONE:
    148 				case TSS_ES_NONE:
    149 				case TPM_ES_SYM_CBC_PKCS5PAD:
    150 					LogDebug("XXX Make sure this is really PKCS5 padded");
    151 				case TR_SYM_MODE_CBC:
    152 					cipher = (EVP_CIPHER *)EVP_aes_128_cbc();
    153 					break;
    154 				case TPM_ES_SYM_OFB:
    155 					cipher = (EVP_CIPHER *)EVP_aes_128_ofb();
    156 					break;
    157 				case TPM_ES_SYM_CNT:
    158 					LogDebug("XXX AES128 in CTR mode unsupp by openssl EVP");
    159 				default:
    160 					LogDebug("Invalid mode in doing symmetric encryption");
    161 					break;
    162 			}
    163 			break;
    164 		case TSS_ALG_DES:
    165 		case TCPA_ALG_DES:
    166 			switch (mode) {
    167 				case TPM_ES_NONE:
    168 				case TSS_ES_NONE:
    169 				case TPM_ES_SYM_CBC_PKCS5PAD:
    170 					LogDebug("XXX Make sure this is really PKCS5 padded");
    171 				case TR_SYM_MODE_CBC:
    172 					cipher = (EVP_CIPHER *)EVP_des_cbc();
    173 					break;
    174 				case TPM_ES_SYM_OFB:
    175 					cipher = (EVP_CIPHER *)EVP_des_ofb();
    176 					break;
    177 				case TPM_ES_SYM_CNT:
    178 					LogDebug("XXX DES in CTR mode unsupp by openssl EVP");
    179 				default:
    180 					LogDebug("Invalid mode in doing symmetric encryption");
    181 					break;
    182 			}
    183 			break;
    184 		case TSS_ALG_3DES:
    185 		case TCPA_ALG_3DES:
    186 			switch (mode) {
    187 				case TPM_ES_NONE:
    188 				case TSS_ES_NONE:
    189 				case TPM_ES_SYM_CBC_PKCS5PAD:
    190 					LogDebug("XXX Make sure this is really PKCS5 padded");
    191 				case TR_SYM_MODE_CBC:
    192 					cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
    193 					break;
    194 				case TPM_ES_SYM_OFB:
    195 					cipher = (EVP_CIPHER *)EVP_des_ede3_ofb();
    196 					break;
    197 				case TPM_ES_SYM_CNT:
    198 					LogDebug("XXX 3DES in CTR mode unsupp by openssl EVP");
    199 				default:
    200 					LogDebug("Invalid mode in doing symmetric encryption");
    201 					break;
    202 			}
    203 			break;
    204 		case TPM_ALG_AES192:
    205 		case TSS_ALG_AES192:
    206 			switch (mode) {
    207 				case TPM_ES_NONE:
    208 				case TSS_ES_NONE:
    209 				case TPM_ES_SYM_CBC_PKCS5PAD:
    210 					LogDebug("XXX Make sure this is really PKCS5 padded");
    211 				case TR_SYM_MODE_CBC:
    212 					cipher = (EVP_CIPHER *)EVP_aes_192_cbc();
    213 					break;
    214 				case TPM_ES_SYM_OFB:
    215 					cipher = (EVP_CIPHER *)EVP_aes_192_ofb();
    216 					break;
    217 				case TPM_ES_SYM_CNT:
    218 					LogDebug("XXX AES192 in CTR mode unsupp by openssl EVP");
    219 				default:
    220 					LogDebug("Invalid mode in doing symmetric encryption");
    221 					break;
    222 			}
    223 			break;
    224 		case TPM_ALG_AES256:
    225 		case TSS_ALG_AES256:
    226 			switch (mode) {
    227 				case TPM_ES_NONE:
    228 				case TSS_ES_NONE:
    229 				case TPM_ES_SYM_CBC_PKCS5PAD:
    230 					LogDebug("XXX Make sure this is really PKCS5 padded");
    231 				case TR_SYM_MODE_CBC:
    232 					cipher = (EVP_CIPHER *)EVP_aes_256_cbc();
    233 					break;
    234 				case TPM_ES_SYM_OFB:
    235 					cipher = (EVP_CIPHER *)EVP_aes_256_ofb();
    236 					break;
    237 				case TPM_ES_SYM_CNT:
    238 					LogDebug("XXX AES256 in CTR mode unsupp by openssl EVP");
    239 				default:
    240 					LogDebug("Invalid mode in doing symmetric encryption");
    241 					break;
    242 			}
    243 			break;
    244 		default:
    245 			LogDebug("Invalid algorithm in doing symmetric encryption");
    246 			break;
    247 	}
    248 
    249 	return cipher;
    250 }
    251 
    252 TSS_RESULT
    253 Trspi_SymEncrypt(UINT16 alg, UINT16 mode, BYTE *key, BYTE *iv, BYTE *in, UINT32 in_len, BYTE *out,
    254 		 UINT32 *out_len)
    255 {
    256 	TSS_RESULT result = TSS_SUCCESS;
    257 	EVP_CIPHER_CTX *ctx = NULL;
    258 	EVP_CIPHER *cipher;
    259 	BYTE *def_iv = NULL, *outiv_ptr;
    260 	UINT32 tmp;
    261 	int iv_len, outiv_len;
    262 
    263 	if (*out_len > INT_MAX)
    264 		outiv_len = INT_MAX;
    265 	else
    266 		outiv_len = *(int *)out_len;
    267 
    268 	if ((cipher = get_openssl_cipher(alg, mode)) == NULL)
    269 		return TSPERR(TSS_E_INTERNAL_ERROR);
    270 
    271 	ctx = EVP_CIPHER_CTX_new();
    272 
    273 	/* If the iv passed in is NULL, create a new random iv and prepend it to the ciphertext */
    274 	iv_len = EVP_CIPHER_iv_length(cipher);
    275 	if (iv == NULL) {
    276 		def_iv = malloc(iv_len);
    277 		if (def_iv == NULL) {
    278 			LogError("malloc of %d bytes failed.", iv_len);
    279 			return TSPERR(TSS_E_OUTOFMEMORY);
    280 		}
    281 		RAND_bytes(def_iv, iv_len);
    282 
    283 		memcpy(out, def_iv, iv_len);
    284 		outiv_ptr = &out[iv_len];
    285 		outiv_len -= iv_len;
    286 	} else {
    287 		def_iv = iv;
    288 		outiv_ptr = out;
    289 	}
    290 
    291 	if (!EVP_EncryptInit(ctx, (const EVP_CIPHER *)cipher, key, def_iv)) {
    292 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    293 		DEBUG_print_openssl_errors();
    294 		goto done;
    295 	}
    296 
    297 	if ((UINT32)outiv_len < in_len + (EVP_CIPHER_CTX_block_size(ctx) * 2) - 1) {
    298 		LogDebug("Not enough space to do symmetric encryption");
    299 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    300 		goto done;
    301 	}
    302 
    303 	if (!EVP_EncryptUpdate(ctx, outiv_ptr, &outiv_len, in, in_len)) {
    304 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    305 		DEBUG_print_openssl_errors();
    306 		goto done;
    307 	}
    308 
    309 	if (!EVP_EncryptFinal(ctx, outiv_ptr + outiv_len, (int *)&tmp)) {
    310 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    311 		DEBUG_print_openssl_errors();
    312 		goto done;
    313 	}
    314 
    315 	outiv_len += tmp;
    316 	*out_len = outiv_len;
    317 done:
    318 	if (def_iv != iv) {
    319 		*out_len += iv_len;
    320 		free(def_iv);
    321 	}
    322 	EVP_CIPHER_CTX_free(ctx);
    323 	return result;
    324 }
    325 
    326 TSS_RESULT
    327 Trspi_SymDecrypt(UINT16 alg, UINT16 mode, BYTE *key, BYTE *iv, BYTE *in, UINT32 in_len, BYTE *out,
    328 		 UINT32 *out_len)
    329 {
    330 	TSS_RESULT result = TSS_SUCCESS;
    331 	EVP_CIPHER_CTX *ctx = NULL;
    332 	EVP_CIPHER *cipher;
    333 	BYTE *def_iv = NULL, *iniv_ptr;
    334 	UINT32 tmp;
    335 	int iv_len, iniv_len;
    336 
    337 	if (in_len > INT_MAX)
    338 		return TSS_E_BAD_PARAMETER;
    339 
    340 	if ((cipher = get_openssl_cipher(alg, mode)) == NULL)
    341 		return TSPERR(TSS_E_INTERNAL_ERROR);
    342 
    343 	ctx = EVP_CIPHER_CTX_new();
    344 
    345 	/* If the iv is NULL, assume that its prepended to the ciphertext */
    346 	if (iv == NULL) {
    347 		iv_len = EVP_CIPHER_iv_length(cipher);
    348 		def_iv = malloc(iv_len);
    349 		if (def_iv == NULL) {
    350 			LogError("malloc of %d bytes failed.", iv_len);
    351 			return TSPERR(TSS_E_OUTOFMEMORY);
    352 		}
    353 
    354 		memcpy(def_iv, in, iv_len);
    355 		iniv_ptr = &in[iv_len];
    356 		iniv_len = in_len - iv_len;
    357 	} else {
    358 		def_iv = iv;
    359 		iniv_ptr = in;
    360 		iniv_len = in_len;
    361 	}
    362 
    363 	if (!EVP_DecryptInit(ctx, cipher, key, def_iv)) {
    364 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    365 		DEBUG_print_openssl_errors();
    366 		goto done;
    367 	}
    368 
    369 	if (!EVP_DecryptUpdate(ctx, out, (int *)out_len, iniv_ptr, iniv_len)) {
    370 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    371 		DEBUG_print_openssl_errors();
    372 		goto done;
    373 	}
    374 
    375 	if (!EVP_DecryptFinal(ctx, out + *out_len, (int *)&tmp)) {
    376 		result = TSPERR(TSS_E_INTERNAL_ERROR);
    377 		DEBUG_print_openssl_errors();
    378 		goto done;
    379 	}
    380 
    381 	*out_len += tmp;
    382 done:
    383 	if (def_iv != iv)
    384 		free(def_iv);
    385 	EVP_CIPHER_CTX_free(ctx);
    386 	return result;
    387 }
    388