xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/trspi/crypto/openssl/symmetric.c (revision 1023804e3833a0bd94414f2545512128f6502c74)
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