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