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  * hash.c - openssl TSS crypto routines
13  *
14  * Kent Yoder <shpedoikal@gmail.com>
15  *
16  */
17 
18 #include <string.h>
19 
20 #include <openssl/opensslv.h>
21 #include <openssl/rsa.h>  // for some reason the MGF1 prototype is in here
22 #include <openssl/evp.h>
23 #include <openssl/hmac.h>
24 #include <openssl/err.h>
25 #include <openssl/sha.h>
26 
27 #include "trousers/tss.h"
28 #include "trousers/trousers.h"
29 #include "trousers_types.h"
30 #include "spi_utils.h"
31 #include "tsplog.h"
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 #if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
44 #define OpenSSL_MGF1(m,mlen,s,slen,md)	PKCS1_MGF1(m,mlen,s,slen,md)
45 #else
46 int MGF1(unsigned char *, long, const unsigned char *, long);
47 #define OpenSSL_MGF1(m,mlen,s,slen,md)	MGF1(m,mlen,s,slen)
48 #endif
49 
50 /*
51  * Hopefully this will make the code clearer since
52  * OpenSSL returns 1 on success
53  */
54 #define EVP_SUCCESS 1
55 
56 TSS_RESULT
Trspi_Hash(UINT32 HashType,UINT32 BufSize,BYTE * Buf,BYTE * Digest)57 Trspi_Hash(UINT32 HashType, UINT32 BufSize, BYTE* Buf, BYTE* Digest)
58 {
59 	EVP_MD_CTX *md_ctx;
60 	unsigned int result_size;
61 	int rv;
62 
63 	md_ctx = EVP_MD_CTX_create();
64 
65 	switch (HashType) {
66 		case TSS_HASH_SHA1:
67 			rv = EVP_DigestInit(md_ctx, EVP_sha1());
68 			break;
69 		default:
70 			rv = TSPERR(TSS_E_BAD_PARAMETER);
71 			goto out;
72 			break;
73 	}
74 
75 	if (rv != EVP_SUCCESS) {
76 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
77 		goto err;
78 	}
79 
80 	rv = EVP_DigestUpdate(md_ctx, Buf, BufSize);
81 	if (rv != EVP_SUCCESS) {
82 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
83 		goto err;
84 	}
85 
86 	result_size = EVP_MD_CTX_size(md_ctx);
87 	rv = EVP_DigestFinal(md_ctx, Digest, &result_size);
88 	if (rv != EVP_SUCCESS) {
89 		rv = TSPERR(TSS_E_INTERNAL_ERROR);
90 		goto err;
91 	} else
92 		rv = TSS_SUCCESS;
93 
94 	goto out;
95 
96 err:
97 	DEBUG_print_openssl_errors();
98 out:
99 	EVP_MD_CTX_destroy(md_ctx);
100         return rv;
101 }
102 
103 TSS_RESULT
Trspi_HashInit(Trspi_HashCtx * ctx,UINT32 HashType)104 Trspi_HashInit(Trspi_HashCtx *ctx, UINT32 HashType)
105 {
106 	int rv;
107 	EVP_MD *md;
108 
109 	switch (HashType) {
110 		case TSS_HASH_SHA1:
111 			md = (EVP_MD *)EVP_sha1();
112 			break;
113 		default:
114 			return TSPERR(TSS_E_BAD_PARAMETER);
115 			break;
116 	}
117 
118 	if ((ctx->ctx = EVP_MD_CTX_create()) == NULL)
119 		return TSPERR(TSS_E_OUTOFMEMORY);
120 
121 	rv = EVP_DigestInit((EVP_MD_CTX *)ctx->ctx, (const EVP_MD *)md);
122 
123 	if (rv != EVP_SUCCESS) {
124 		DEBUG_print_openssl_errors();
125 		return TSPERR(TSS_E_INTERNAL_ERROR);
126 	}
127 
128 	return TSS_SUCCESS;
129 }
130 
131 TSS_RESULT
Trspi_HashUpdate(Trspi_HashCtx * ctx,UINT32 size,BYTE * data)132 Trspi_HashUpdate(Trspi_HashCtx *ctx, UINT32 size, BYTE *data)
133 {
134 	int rv;
135 
136 	if (ctx == NULL || ctx->ctx == NULL)
137 		return TSPERR(TSS_E_INTERNAL_ERROR);
138 
139 	if (data == NULL && size)
140 		return TSPERR(TSS_E_BAD_PARAMETER);
141 
142 	if (!size)
143 		return TSS_SUCCESS;
144 
145 	rv = EVP_DigestUpdate(ctx->ctx, data, size);
146 	if (rv != EVP_SUCCESS) {
147 		DEBUG_print_openssl_errors();
148 		free(ctx->ctx);
149 		ctx->ctx = NULL;
150 		return TSPERR(TSS_E_INTERNAL_ERROR);
151 	}
152 
153 	return TSS_SUCCESS;
154 }
155 
156 TSS_RESULT
Trspi_HashFinal(Trspi_HashCtx * ctx,BYTE * digest)157 Trspi_HashFinal(Trspi_HashCtx *ctx, BYTE *digest)
158 {
159 	int rv;
160 	UINT32 result_size;
161 
162 	if (ctx == NULL || ctx->ctx == NULL)
163 		return TSPERR(TSS_E_INTERNAL_ERROR);
164 
165 	result_size = EVP_MD_CTX_size((EVP_MD_CTX *)ctx->ctx);
166 	rv = EVP_DigestFinal(ctx->ctx, digest, &result_size);
167 	if (rv != EVP_SUCCESS)
168 		return TSPERR(TSS_E_INTERNAL_ERROR);
169 
170 	free(ctx->ctx);
171 	ctx->ctx = NULL;
172 
173 	return TSS_SUCCESS;
174 }
175 
176 UINT32
Trspi_HMAC(UINT32 HashType,UINT32 SecretSize,BYTE * Secret,UINT32 BufSize,BYTE * Buf,BYTE * hmacOut)177 Trspi_HMAC(UINT32 HashType, UINT32 SecretSize, BYTE* Secret, UINT32 BufSize, BYTE* Buf, BYTE* hmacOut)
178 {
179 	/*HMAC_CTX hmac_ctx;*/
180 	const EVP_MD *md;
181 	unsigned int len;
182 	int rv = TSS_SUCCESS;
183 
184 	switch (HashType) {
185 		case TSS_HASH_SHA1:
186 			md = EVP_sha1();
187 			break;
188 		default:
189 			rv = TSPERR(TSS_E_BAD_PARAMETER);
190 			goto out;
191 			break;
192 	}
193 
194 	len = EVP_MD_size(md);
195 
196 	HMAC(md, Secret, SecretSize, Buf, BufSize, hmacOut, &len);
197 out:
198 	return rv;
199 }
200 
201 TSS_RESULT
Trspi_MGF1(UINT32 alg,UINT32 seedLen,BYTE * seed,UINT32 outLen,BYTE * out)202 Trspi_MGF1(UINT32 alg, UINT32 seedLen, BYTE *seed, UINT32 outLen, BYTE *out)
203 {
204 	const EVP_MD *md;
205 	long olen = outLen, slen = seedLen;
206 	int rv = TSS_SUCCESS;
207 
208 	switch (alg) {
209 		case TSS_HASH_SHA1:
210 			md = EVP_sha1();
211 			break;
212 		default:
213 			rv = TSPERR(TSS_E_BAD_PARAMETER);
214 			goto out;
215 			break;
216 	}
217 
218 	rv = OpenSSL_MGF1(out, olen, seed, slen, md);
219 out:
220 	return rv;
221 }
222