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@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
Trspi_Encrypt_ECB(UINT16 alg,BYTE * key,BYTE * in,UINT32 in_len,BYTE * out,UINT32 * out_len)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
Trspi_Decrypt_ECB(UINT16 alg,BYTE * key,BYTE * in,UINT32 in_len,BYTE * out,UINT32 * out_len)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 *
get_openssl_cipher(UINT16 alg,UINT16 mode)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
Trspi_SymEncrypt(UINT16 alg,UINT16 mode,BYTE * key,BYTE * iv,BYTE * in,UINT32 in_len,BYTE * out,UINT32 * out_len)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
Trspi_SymDecrypt(UINT16 alg,UINT16 mode,BYTE * key,BYTE * iv,BYTE * in,UINT32 in_len,BYTE * out,UINT32 * out_len)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