blob: 192816086de1589e5bbcd678183693d38676c6ba [file] [log] [blame]
Juergen Reppff821bd2017-12-11 15:21:42 +01001/*******************************************************************************
2 * Copyright 2017, Fraunhofer SIT sponsored by Infineon Technologies AG
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
26 *******************************************************************************/
Juergen Reppff821bd2017-12-11 15:21:42 +010027
Juergen Repp4a738892018-04-24 12:05:48 +020028#define _GNU_SOURCE
29
Juergen Reppff821bd2017-12-11 15:21:42 +010030#include <gcrypt.h>
Juergen Repp4a738892018-04-24 12:05:48 +020031#include <stdio.h>
Juergen Reppff821bd2017-12-11 15:21:42 +010032
Juergen Repp62097182018-03-19 18:04:42 +010033#include "tss2_esys.h"
Juergen Repp62097182018-03-19 18:04:42 +010034
35#include "esys_crypto.h"
36#include "esys_iutil.h"
37#include "esys_mu.h"
38#define LOGMODULE esys
39#include "util/log.h"
Juergen Reppff821bd2017-12-11 15:21:42 +010040
41/** Context to hold temporary values for iesys_crypto */
42typedef struct _IESYS_CRYPTO_CONTEXT {
43 enum {
44 IESYS_CRYPTOGCRY_TYPE_HASH = 1,
45 IESYS_CRYPTOGCRY_TYPE_HMAC,
dantpmf6ef2472018-04-06 15:21:59 -070046 } type; /**< The type of context to hold; hash or hmac */
Juergen Reppff821bd2017-12-11 15:21:42 +010047 union {
48 struct {
49 gcry_md_hd_t gcry_context;
50 int gcry_hash_alg;
51 size_t hash_len;
52 } hash; /**< the state variables for a hash context */
53 struct {
54 gcry_mac_hd_t gcry_context;
55 int gcry_hmac_alg;
56 size_t hmac_len;
57 } hmac; /**< the state variables for an hmac context */
58 };
59} IESYS_CRYPTOGCRY_CONTEXT;
60
61/** Provide the digest size for a given hash algorithm
62 *
63 * This function provides the size of the digest for a given hash algorithm
64 *
65 * @param hashAlg [in] The hash algorithm to get the size for
66 * @param size [out] The side of a digest of the hash algorithm
67 * @returnval TSS2_RC_SUCCESS on success
68 * @returnval TSS2_SYS_RC_BAD_VALUE if hashAlg is unknown or unsupported
69 */
70TSS2_RC
71iesys_crypto_hash_get_digest_size(TPM2_ALG_ID hashAlg, size_t * size)
72{
73 LOG_TRACE("call: hashAlg=%"PRIu16" size=%p", hashAlg, size);
Juergen Repp8fd96e42018-04-24 14:29:06 +020074 if (size == NULL) {
75 LOG_ERROR("Null-Pointer passed");
76 return TSS2_ESYS_RC_BAD_REFERENCE;
77 }
Juergen Reppff821bd2017-12-11 15:21:42 +010078 switch (hashAlg) {
79 case TPM2_ALG_SHA1:
80 *size = TPM2_SHA1_DIGEST_SIZE;
81 break;
82 case TPM2_ALG_SHA256:
83 *size = TPM2_SHA256_DIGEST_SIZE;
84 break;
85 case TPM2_ALG_SHA384:
86 *size = TPM2_SHA384_DIGEST_SIZE;
87 break;
88 case TPM2_ALG_SHA512:
89 *size = TPM2_SHA512_DIGEST_SIZE;
90 break;
91 case TPM2_ALG_SM3_256:
92 *size = TPM2_SM3_256_DIGEST_SIZE;
93 break;
94 default:
95 LOG_ERROR("Unsupported hash algorithm (%"PRIu16")", hashAlg);
Juergen Repp8fd96e42018-04-24 14:29:06 +020096 return TSS2_ESYS_RC_BAD_VALUE;
Juergen Reppff821bd2017-12-11 15:21:42 +010097 }
98 LOG_TRACE("return: *size=%zu", *size);
99 return TSS2_RC_SUCCESS;
100}
101
102
103TSS2_RC
104iesys_cryptogcry_hash_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,
105 TPM2_ALG_ID hashAlg)
106{
107 LOG_TRACE("call: context=%p hashAlg=%"PRIu16, context, hashAlg);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200108 return_if_null(context, "Context is NULL", TSS2_ESYS_RC_BAD_REFERENCE);
Juergen Reppff821bd2017-12-11 15:21:42 +0100109 IESYS_CRYPTOGCRY_CONTEXT *mycontext;
110 mycontext = calloc(1, sizeof(IESYS_CRYPTOGCRY_CONTEXT));
Juergen Repp8fd96e42018-04-24 14:29:06 +0200111 return_if_null(mycontext, "Out of Memory", TSS2_ESYS_RC_MEMORY);
Juergen Reppff821bd2017-12-11 15:21:42 +0100112 mycontext->type = IESYS_CRYPTOGCRY_TYPE_HASH;
113
114 switch (hashAlg) {
115 case TPM2_ALG_SHA1:
116 mycontext->hash.gcry_hash_alg = GCRY_MD_SHA1;
117 break;
118 case TPM2_ALG_SHA256:
119 mycontext->hash.gcry_hash_alg = GCRY_MD_SHA256;
120 break;
121 case TPM2_ALG_SHA384:
122 mycontext->hash.gcry_hash_alg = GCRY_MD_SHA384;
123 break;
124 default:
125 LOG_ERROR("Unsupported hash algorithm (%"PRIu16")", hashAlg);
126 free(mycontext);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200127 return TSS2_ESYS_RC_NOT_IMPLEMENTED;
Juergen Reppff821bd2017-12-11 15:21:42 +0100128 }
129 int hash_len = gcry_md_get_algo_dlen(mycontext->hash.gcry_hash_alg);
130 if (hash_len <= 0) {
131 LOG_ERROR("Unsupported hash algorithm (%"PRIu16")", hashAlg);
132 free(mycontext);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200133 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100134 }
135 mycontext->hash.hash_len = hash_len;
136
137 gcry_error_t r = gcry_md_open(&mycontext->hash.gcry_context,
138 mycontext->hash.gcry_hash_alg, 0);
139 if (r != 0) {
140 LOG_ERROR("GCry error.");
141 free(mycontext);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200142 return TSS2_ESYS_RC_GENERAL_FAILURE;
143 }
144
145 if (context == NULL) {
146 LOG_ERROR("Null-Pointer passed");
147 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100148 }
149
150 *context = (IESYS_CRYPTO_CONTEXT_BLOB *) mycontext;
151
152 return TSS2_RC_SUCCESS;
153}
154
155TSS2_RC
156iesys_cryptogcry_hash_update(IESYS_CRYPTO_CONTEXT_BLOB * context,
157 const uint8_t * buffer, size_t size)
158{
159 LOG_TRACE("called for context %p, buffer %p and size %zd", context, buffer,
160 size);
161 if (context == NULL || buffer == NULL) {
162 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200163 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100164 }
165 IESYS_CRYPTOGCRY_CONTEXT *mycontext = (IESYS_CRYPTOGCRY_CONTEXT *) context;
166 if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HASH) {
167 LOG_ERROR("bad context");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200168 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100169 }
170
171 LOGBLOB_TRACE(buffer, size, "Updating hash with");
172
173 gcry_md_write(mycontext->hash.gcry_context, buffer, size);
174
175 return TSS2_RC_SUCCESS;
176}
177
178TSS2_RC
179iesys_cryptogcry_hash_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context, TPM2B * b)
180{
181 LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
182 if (context == NULL || b == NULL) {
183 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200184 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100185 }
186 TSS2_RC ret = iesys_cryptogcry_hash_update(context, &b->buffer[0], b->size);
187 return ret;
188}
189
190TSS2_RC
191iesys_cryptogcry_hash_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,
192 uint8_t * buffer, size_t * size)
193{
194 LOG_TRACE("called for context-pointer %p, buffer %p and size-pointer %p",
195 context, buffer, size);
196 if (context == NULL || *context == NULL || buffer == NULL || size == NULL) {
197 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200198 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100199 }
200 IESYS_CRYPTOGCRY_CONTEXT *mycontext = * context;
201 if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HASH) {
202 LOG_ERROR("bad context");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200203 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100204 }
205
206 if (*size < mycontext->hash.hash_len) {
207 LOG_ERROR("Buffer too small");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200208 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100209 }
210
211 uint8_t *cpHash = gcry_md_read(mycontext->hash.gcry_context,
212 mycontext->hash.gcry_hash_alg);
213 if (cpHash == NULL) {
214 LOG_ERROR("GCry error.");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200215 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100216 }
217
218 LOGBLOB_TRACE(cpHash, mycontext->hash.hash_len, "read hash result");
219
220 *size = mycontext->hash.hash_len;
221 memmove(buffer, cpHash, *size);
222
223 gcry_md_close(mycontext->hash.gcry_context);
224
225 free(mycontext);
226 *context = NULL;
227
228 return TSS2_RC_SUCCESS;
229}
230
231TSS2_RC
232iesys_cryptogcry_hash_finish2b(IESYS_CRYPTO_CONTEXT_BLOB ** context, TPM2B * b)
233{
234 LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
235 if (context == NULL || *context == NULL || b == NULL) {
236 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200237 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100238 }
239 size_t s = b->size;
240 TSS2_RC ret = iesys_cryptogcry_hash_finish(context, &b->buffer[0], &s);
241 b->size = s;
242 return ret;
243}
244
245void
246iesys_cryptogcry_hash_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)
247{
248 LOG_TRACE("called for context-pointer %p", context);
249 if (context == NULL || *context == NULL) {
250 LOG_DEBUG("Null-Pointer passed");
251 return;
252 }
253 IESYS_CRYPTOGCRY_CONTEXT *mycontext =
254 (IESYS_CRYPTOGCRY_CONTEXT *) * context;
255 if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HASH) {
256 LOG_DEBUG("bad context");
257 return;
258 }
259
260 gcry_md_close(mycontext->hash.gcry_context);
261 free(mycontext);
262 *context = NULL;
263}
264
265/* HMAC */
266
267TSS2_RC
268iesys_cryptogcry_hmac_start(IESYS_CRYPTO_CONTEXT_BLOB ** context,
269 TPM2_ALG_ID hmacAlg,
270 const uint8_t * key, size_t size)
271{
272 TSS2_RC r;
273
274 LOG_TRACE("called for context-pointer %p and hmacAlg %d", context, hmacAlg);
275 LOGBLOB_TRACE(key, size, "Starting hmac with");
276 if (context == NULL || key == NULL) {
277 LOG_ERROR("Null-Pointer passed in for context");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200278 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100279 }
280 IESYS_CRYPTOGCRY_CONTEXT *mycontext =
281 calloc(1, sizeof(IESYS_CRYPTOGCRY_CONTEXT));
282 if (mycontext == NULL) {
283 LOG_ERROR("Out of Memory");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200284 return TSS2_ESYS_RC_MEMORY;
Juergen Reppff821bd2017-12-11 15:21:42 +0100285 }
286
287 switch (hmacAlg) {
288 case TPM2_ALG_SHA1:
289 mycontext->hmac.gcry_hmac_alg = GCRY_MAC_HMAC_SHA1;
290 break;
291 case TPM2_ALG_SHA256:
292 mycontext->hmac.gcry_hmac_alg = GCRY_MAC_HMAC_SHA256;
293 break;
294 default:
295 LOG_ERROR("Unsupported hmac algo.");
296 free(mycontext);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200297 return TSS2_ESYS_RC_NOT_IMPLEMENTED;
Juergen Reppff821bd2017-12-11 15:21:42 +0100298 }
299
300 int hmac_len = gcry_mac_get_algo_maclen(mycontext->hmac.gcry_hmac_alg);
301 if (hmac_len <= 0) {
302 LOG_ERROR("GCry error.");
303 free(mycontext);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200304 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100305 }
306
307 mycontext->type = IESYS_CRYPTOGCRY_TYPE_HMAC;
308 mycontext->hmac.hmac_len = hmac_len;
309
310 r = gcry_mac_open(&mycontext->hmac.gcry_context,
311 mycontext->hmac.gcry_hmac_alg, 0, NULL);
312 if (r != 0) {
313 LOG_ERROR("GCry error.");
314 free(mycontext);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200315 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100316 }
317
318 r = gcry_mac_setkey(mycontext->hmac.gcry_context, key, size);
319 if (r != 0) {
320 LOG_ERROR("GCry error.");
321 gcry_mac_close(mycontext->hmac.gcry_context);
322 free(mycontext);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200323 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100324 }
325
326 *context = (IESYS_CRYPTO_CONTEXT_BLOB *) mycontext;
327
328 return TSS2_RC_SUCCESS;
329}
330
331TSS2_RC
332iesys_cryptogcry_hmac_start2b(IESYS_CRYPTO_CONTEXT_BLOB ** context,
333 TPM2_ALG_ID hmacAlg, TPM2B * b)
334{
335 LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
336 if (context == NULL || b == NULL) {
337 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200338 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100339 }
340 TSS2_RC ret = iesys_cryptogcry_hmac_start(context, hmacAlg, &b->buffer[0],
341 b->size);
342 return ret;
343}
344
345TSS2_RC
346iesys_cryptogcry_hmac_update(IESYS_CRYPTO_CONTEXT_BLOB * context,
347 const uint8_t * buffer, size_t size)
348{
349 LOG_TRACE("called for context %p, buffer %p and size %zd",
350 context, buffer, size);
351 if (context == NULL || buffer == NULL) {
352 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200353 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100354 }
355 IESYS_CRYPTOGCRY_CONTEXT *mycontext = (IESYS_CRYPTOGCRY_CONTEXT *) context;
356 if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HMAC) {
357 LOG_ERROR("bad context");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200358 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100359 }
360
361 LOGBLOB_TRACE(buffer, size, "Updating hmac with");
362
363 gcry_mac_write(mycontext->hmac.gcry_context, buffer, size);
364
365 return TSS2_RC_SUCCESS;
366}
367
368TSS2_RC
369iesys_cryptogcry_hmac_update2b(IESYS_CRYPTO_CONTEXT_BLOB * context, TPM2B * b)
370{
371 LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
372 if (context == NULL || b == NULL) {
373 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200374 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100375 }
376 TSS2_RC ret = iesys_cryptogcry_hmac_update(context, &b->buffer[0], b->size);
377 return ret;
378}
379
380TSS2_RC
381iesys_cryptogcry_hmac_finish(IESYS_CRYPTO_CONTEXT_BLOB ** context,
382 uint8_t * buffer, size_t * size)
383{
384 LOG_TRACE("called for context-pointer %p, buffer %p and size-pointer %p",
385 context, buffer, size);
386 if (context == NULL || *context == NULL || buffer == NULL || size == NULL) {
387 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200388 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100389 }
390 IESYS_CRYPTOGCRY_CONTEXT *mycontext =
391 (IESYS_CRYPTOGCRY_CONTEXT *) * context;
392 if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HMAC) {
393 LOG_ERROR("bad context");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200394 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100395 }
396
397 if (*size < mycontext->hmac.hmac_len) {
398 LOG_ERROR("Buffer too small");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200399 return TSS2_ESYS_RC_BAD_SIZE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100400 }
401
402 TSS2_RC r = gcry_mac_read(mycontext->hmac.gcry_context, buffer, size);
403 if (r != 0) {
404 LOG_ERROR("GCry error.");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200405 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100406 }
407
408 LOGBLOB_TRACE(buffer, *size, "read hmac result");
409
410 gcry_mac_close(mycontext->hmac.gcry_context);
411
412 free(mycontext);
413 *context = NULL;
414
415 return TSS2_RC_SUCCESS;
416}
417
418TSS2_RC
419iesys_cryptogcry_hmac_finish2b(IESYS_CRYPTO_CONTEXT_BLOB ** context, TPM2B * b)
420{
421 LOG_TRACE("called for context-pointer %p and 2b-pointer %p", context, b);
422 if (context == NULL || *context == NULL || b == NULL) {
423 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200424 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100425 }
426 size_t s = b->size;
427 TSS2_RC ret = iesys_cryptogcry_hmac_finish(context, &b->buffer[0], &s);
428 b->size = s;
429 return ret;
430}
431
432void
433iesys_cryptogcry_hmac_abort(IESYS_CRYPTO_CONTEXT_BLOB ** context)
434{
435 LOG_TRACE("called for context-pointer %p", context);
436 if (context == NULL || *context == NULL) {
437 LOG_DEBUG("Null-Pointer passed");
438 return;
439 }
440 if (*context != NULL) {
441 IESYS_CRYPTOGCRY_CONTEXT *mycontext =
442 (IESYS_CRYPTOGCRY_CONTEXT *) * context;
443 if (mycontext->type != IESYS_CRYPTOGCRY_TYPE_HMAC) {
444 LOG_DEBUG("bad context");
445 return;
446 }
447
448 gcry_mac_close(mycontext->hmac.gcry_context);
449
450 free(mycontext);
451 *context = NULL;
452 }
453}
454
455TSS2_RC
456iesys_crypto_pHash(TPM2_ALG_ID alg,
457 const uint8_t rcBuffer[4],
458 const uint8_t ccBuffer[4],
459 const TPM2B_NAME * name1,
460 const TPM2B_NAME * name2,
461 const TPM2B_NAME * name3,
462 const uint8_t * pBuffer,
463 size_t pBuffer_size, uint8_t * pHash, size_t * pHash_size)
464{
465 LOG_TRACE("called");
466 if (ccBuffer == NULL || pBuffer == NULL || pHash == NULL
467 || pHash_size == NULL) {
468 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200469 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100470 }
471
472 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
473
474 TSS2_RC r = iesys_crypto_hash_start(&cryptoContext, alg);
475 return_if_error(r, "Error");
476
477 if (rcBuffer != NULL) {
478 r = iesys_crypto_hash_update(cryptoContext, &rcBuffer[0], 4);
479 goto_if_error(r, "Error", error);
480 }
481
482 r = iesys_crypto_hash_update(cryptoContext, &ccBuffer[0], 4);
483 goto_if_error(r, "Error", error);
484
485 if (name1 != NULL) {
486 r = iesys_crypto_hash_update2b(cryptoContext, (TPM2B *) name1);
487 goto_if_error(r, "Error", error);
488 }
489
490 if (name2 != NULL) {
491 r = iesys_crypto_hash_update2b(cryptoContext, (TPM2B *) name2);
492 goto_if_error(r, "Error", error);
493 }
494
495 if (name3 != NULL) {
496 r = iesys_crypto_hash_update2b(cryptoContext, (TPM2B *) name3);
497 goto_if_error(r, "Error", error);
498 }
499
500 r = iesys_crypto_hash_update(cryptoContext, pBuffer, pBuffer_size);
501 goto_if_error(r, "Error", error);
502
503 r = iesys_crypto_hash_finish(&cryptoContext, pHash, pHash_size);
504 goto_if_error(r, "Error", error);
505
506 return r;
507
508 error:
509 iesys_crypto_hash_abort(&cryptoContext);
510 return r;
511}
512
513TSS2_RC
514iesys_crypto_authHmac(TPM2_ALG_ID alg,
515 uint8_t * hmacKey, size_t hmacKeySize,
516 const uint8_t * pHash,
517 size_t pHash_size,
518 const TPM2B_NONCE * nonceNewer,
519 const TPM2B_NONCE * nonceOlder,
520 const TPM2B_NONCE * nonceDecrypt,
521 const TPM2B_NONCE * nonceEncrypt,
522 TPMA_SESSION sessionAttributes, TPM2B_AUTH * hmac)
523{
524 LOG_TRACE("called");
525 if (hmacKey == NULL || pHash == NULL || nonceNewer == NULL ||
526 nonceOlder == NULL || hmac == NULL) {
527 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200528 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100529 }
530
531 uint8_t sessionAttribs[sizeof(sessionAttributes)];
532 size_t sessionAttribs_size = 0;
533
534 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
535
536 TSS2_RC r =
537 iesys_crypto_hmac_start(&cryptoContext, alg, hmacKey, hmacKeySize);
538 return_if_error(r, "Error");
539
540 r = iesys_crypto_hmac_update(cryptoContext, pHash, pHash_size);
541 goto_if_error(r, "Error", error);
542
543 r = iesys_crypto_hmac_update2b(cryptoContext, (TPM2B *) nonceNewer);
544 goto_if_error(r, "Error", error);
545
546 r = iesys_crypto_hmac_update2b(cryptoContext, (TPM2B *) nonceOlder);
547 goto_if_error(r, "Error", error);
548
549 if (nonceDecrypt != NULL) {
550 r = iesys_crypto_hmac_update2b(cryptoContext, (TPM2B *) nonceDecrypt);
551 goto_if_error(r, "Error", error);
552 }
553
554 if (nonceEncrypt != NULL) {
555 r = iesys_crypto_hmac_update2b(cryptoContext, (TPM2B *) nonceEncrypt);
556 goto_if_error(r, "Error", error);
557 }
558
559 r = Tss2_MU_TPMA_SESSION_Marshal(sessionAttributes,
560 &sessionAttribs[0],
561 sizeof(sessionAttribs),
562 &sessionAttribs_size);
563 goto_if_error(r, "Error", error);
564
565 r = iesys_crypto_hmac_update(cryptoContext, &sessionAttribs[0],
566 sessionAttribs_size);
567 goto_if_error(r, "Error", error);
568
569 r = iesys_crypto_hmac_finish2b(&cryptoContext, (TPM2B *) hmac);
570 goto_if_error(r, "Error", error);
571
572 return r;
573
574 error:
575 iesys_crypto_hmac_abort(&cryptoContext);
576 return r;
577
578}
579
580TSS2_RC
581iesys_crypto_KDFaHmac(TPM2_ALG_ID alg,
582 uint8_t * hmacKey,
583 size_t hmacKeySize,
584 uint32_t counter,
585 const char *label,
586 TPM2B_NONCE * contextU,
587 TPM2B_NONCE * contextV,
588 uint32_t bitlength, uint8_t * hmac, size_t * hmacSize)
589{
590 LOG_TRACE("called");
591 if (hmacKey == NULL || contextU == NULL || contextV == NULL) {
592 LOG_ERROR("Null-Pointer passed");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200593 return TSS2_ESYS_RC_BAD_REFERENCE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100594 }
595
596 uint8_t buffer32[sizeof(uint32_t)];
597 size_t buffer32_size = 0;
598
599 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
600
601 TSS2_RC r =
602 iesys_crypto_hmac_start(&cryptoContext, alg, hmacKey, hmacKeySize);
603 return_if_error(r, "Error");
604
605 r = Tss2_MU_UINT32_Marshal(counter, &buffer32[0], sizeof(UINT32),
Juergen Repp8fd96e42018-04-24 14:29:06 +0200606 &buffer32_size);
607 goto_if_error(r, "Marsahling", error);
Juergen Reppff821bd2017-12-11 15:21:42 +0100608 r = iesys_crypto_hmac_update(cryptoContext, &buffer32[0], buffer32_size);
609 goto_if_error(r, "HMAC-Update", error);
610
611 if (label != NULL) {
612 size_t lsize = strlen(label) + 1;
613 r = iesys_crypto_hmac_update(cryptoContext, (uint8_t *) label, lsize);
614 goto_if_error(r, "Error", error);
615 }
616
617 r = iesys_crypto_hmac_update2b(cryptoContext, (TPM2B *) contextU);
618 goto_if_error(r, "Error", error);
619
620 r = iesys_crypto_hmac_update2b(cryptoContext, (TPM2B *) contextV);
621 goto_if_error(r, "Error", error);
622
623 buffer32_size = 0;
624 r = Tss2_MU_UINT32_Marshal(bitlength, &buffer32[0], sizeof(UINT32),
625 &buffer32_size);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200626 goto_if_error(r, "Marsahling", error);
Juergen Reppff821bd2017-12-11 15:21:42 +0100627 r = iesys_crypto_hmac_update(cryptoContext, &buffer32[0], buffer32_size);
628 goto_if_error(r, "Error", error);
629
630 r = iesys_crypto_hmac_finish(&cryptoContext, hmac, hmacSize);
631 goto_if_error(r, "Error", error);
632
633 return r;
634
635 error:
636 iesys_crypto_hmac_abort(&cryptoContext);
637 return r;
638}
639
640TSS2_RC
641iesys_crypto_KDFa(TPM2_ALG_ID hashAlg,
642 uint8_t * hmacKey,
643 size_t hmacKeySize,
644 const char *label,
645 TPM2B_NONCE * contextU,
646 TPM2B_NONCE * contextV,
Juergen Reppf29cfef2018-03-27 14:18:07 +0200647 uint32_t bitLength, uint32_t * counterInOut, BYTE * outKey, BOOL use_digest_size)
Juergen Reppff821bd2017-12-11 15:21:42 +0100648{
649 LOG_DEBUG("IESYS KDFa hmac key hashAlg: %i label: %s bitLength: %i",
650 hashAlg, label, bitLength);
651 if (counterInOut != NULL)
652 LOG_TRACE("IESYS KDFa hmac key counterInOut: %i", *counterInOut);
653 LOGBLOB_DEBUG(hmacKey, hmacKeySize, "IESYS KDFa hmac key");
654
655 LOGBLOB_DEBUG(&contextU->buffer[0], contextU->size,
656 "IESYS KDFa contextU key");
657 LOGBLOB_DEBUG(&contextV->buffer[0], contextV->size,
658 "IESYS KDFa contextV key");
659 BYTE *subKey = outKey;
660 UINT32 counter = 0;
661 INT32 bytes = 0;
662 size_t hlen = 0;
663 TSS2_RC r = iesys_crypto_hash_get_digest_size(hashAlg, &hlen);
664 return_if_error(r, "Error");
665 if (counterInOut != NULL)
666 counter = *counterInOut;
Juergen Reppf29cfef2018-03-27 14:18:07 +0200667 bytes = use_digest_size ? hlen : (bitLength + 7) / 8;
Juergen Reppff821bd2017-12-11 15:21:42 +0100668 LOG_DEBUG("IESYS KDFa hmac key bytes: %i", bytes);
669 for (; bytes > 0; subKey = &subKey[hlen], bytes = bytes - hlen) {
670 LOG_TRACE("IESYS KDFa hmac key bytes: %i", bytes);
671 //if(bytes < (INT32)hlen)
672 // hlen = bytes;
673 counter++;
674 r = iesys_crypto_KDFaHmac(hashAlg, hmacKey,
675 hmacKeySize, counter, label, contextU,
676 contextV, bitLength, &subKey[0], &hlen);
677 return_if_error(r, "Error");
678 }
679 if ((bitLength % 8) != 0)
680 outKey[0] &= ((1 << (bitLength % 8)) - 1);
681 if (counterInOut != NULL)
682 *counterInOut = counter;
683 LOGBLOB_DEBUG(outKey, (bitLength + 7) / 8, "IESYS KDFa key");
684 return TPM2_RC_SUCCESS;
685}
686
687TSS2_RC
688iesys_cryptogcry_random2b(TPM2B_NONCE * nonce, size_t num_bytes)
689{
690 if (num_bytes == 0) {
691 nonce->size = sizeof(TPMU_HA);
692 } else {
693 nonce->size = num_bytes;
694 }
695 /*
696 * possible values for random level:
697 * GCRY_WEAK_RANDOM GCRY_STRONG_RANDOM GCRY_VERY_STRONG_RANDOM
698 */
699 gcry_randomize(&nonce->buffer[0], nonce->size, GCRY_STRONG_RANDOM);
700 return TSS2_RC_SUCCESS;
701}
702
Juergen Repp4a738892018-04-24 12:05:48 +0200703/** Compute KDFe as described in tpm spec part 1 C 6.1
704 *
705 * @possible
706 * @parm hashAlg [IN] The nameAlg of the recipient key.
707 * @parm Z [IN] the x coordinate (xP) of the product (P) of a public point and a
708 * private key.
709 * @parm label [IN] KDF label.
710 * @parm partyUInfo [IN] The x-coordinate of the secret exchange value (Qe,U).
711 * @parm partyVInfo [IN] The x-coordinate of a public key (Qs,V).
712 * @parm bit_size [IN] Bit size of generated key.
713 * @parm key [OUT] Key buffer.
714 * @returnval TSS2_RC_SUCCESS or TODO
715 */
716TSS2_RC
717iesys_cryptogcry_KDFe(TPM2_ALG_ID hashAlg,
718 TPM2B_ECC_PARAMETER *Z,
719 const char *label,
720 TPM2B_ECC_PARAMETER *partyUInfo,
721 TPM2B_ECC_PARAMETER *partyVInfo,
722 UINT32 bit_size,
723 BYTE *key)
724{
725 TSS2_RC r = TSS2_RC_SUCCESS;
726 size_t hash_len;
727 INT16 byte_size = (INT16)((bit_size +7) / 8);
728 BYTE *stream = key;
729 IESYS_CRYPTO_CONTEXT_BLOB *cryptoContext;
730 BYTE counter_buffer[4];
731 UINT32 counter = 0;
732 size_t offset;
733
734 LOG_DEBUG("IESYS KDFe hashAlg: %i label: %s bitLength: %i",
735 hashAlg, label, bit_size);
736 LOGBLOB_DEBUG(&partyUInfo->buffer[0], partyUInfo->size, "partyUInfo");
737 LOGBLOB_DEBUG(&partyVInfo->buffer[0], partyVInfo->size, "partyVInfo");
738 r = iesys_crypto_hash_get_digest_size(hashAlg, &hash_len);
739 return_if_error(r, "Hash algorithm not supported.");
740
741 if(hashAlg == TPM2_ALG_NULL || byte_size == 0) {
742 LOG_DEBUG("Bad parameters for KDFe");
743 return TSS2_ESYS_RC_BAD_VALUE;
744 }
745
746 /* Fill seed key with hash of counter, Z, label, partyUInfo, and partyVInfo */
747 for (; byte_size > 0; stream = &stream[hash_len], byte_size = byte_size - hash_len)
748 {
749 counter ++;
750 r = iesys_crypto_hash_start(&cryptoContext, hashAlg);
751 return_if_error(r, "Error hash start");
752
753 offset = 0;
754 r = Tss2_MU_UINT32_Marshal(counter, &counter_buffer[0], 4, &offset);
755 goto_if_error(r, "Error Tss2_MU_UINT32_Marshal", error);
756
757 r = iesys_crypto_hash_update(cryptoContext, &counter_buffer[0], 4);
758 goto_if_error(r, "Error hash update", error);
759
760 if (Z != NULL) {
761 r = iesys_crypto_hash_update2b(cryptoContext, (TPM2B *) Z);
762 goto_if_error(r, "Error hash update2b", error);
763 }
764
765 if (label != NULL) {
766 size_t lsize = strlen(label) + 1;
767 r = iesys_crypto_hash_update(cryptoContext, (uint8_t *) label, lsize);
768 goto_if_error(r, "Error hash update", error);
769 }
770
771 if (partyUInfo != NULL) {
772 r = iesys_crypto_hash_update2b(cryptoContext, (TPM2B *) partyUInfo);
773 goto_if_error(r, "Error hash update2b", error);
774 }
775
776 if (partyVInfo != NULL) {
777 r = iesys_crypto_hash_update2b(cryptoContext, (TPM2B *) partyVInfo);
Juergen Repp8fd96e42018-04-24 14:29:06 +0200778 goto_if_error(r, "Error hash update2b", error);
Juergen Repp4a738892018-04-24 12:05:48 +0200779 }
780 r = iesys_crypto_hash_finish(&cryptoContext, (uint8_t *) stream, &hash_len);
781 goto_if_error(r, "Error", error);
782 }
783 LOGBLOB_DEBUG(key, bit_size/8, "Result KDFe");
784 if((bit_size % 8) != 0)
785 key[0] &= ((1 << (bit_size % 8)) - 1);
786 return r;
787
788 error:
789 iesys_crypto_hmac_abort(&cryptoContext);
790 return r;
791}
792
Juergen Reppff821bd2017-12-11 15:21:42 +0100793TSS2_RC
794iesys_cryptogcry_pk_encrypt(TPM2B_PUBLIC * key,
795 size_t in_size,
796 BYTE * in_buffer,
797 size_t max_out_size,
798 BYTE * out_buffer,
799 size_t * out_size, const char *label)
800{
801 TSS2_RC r;
Juergen Reppff821bd2017-12-11 15:21:42 +0100802 gcry_error_t err;
803 char *hash_alg;
804 size_t lsize = 0;
805 BYTE exponent[4] = { 0x00, 0x01, 0x00, 0x01 };
806 //gcry_mpi_t mpi_exp;
807 char *padding;
Juergen Reppff821bd2017-12-11 15:21:42 +0100808 gcry_sexp_t sexp_data, sexp_key, sexp_cipher, sexp_cipher_a;
809 if (label != NULL)
810 lsize = strlen(label) + 1;
811 switch (key->publicArea.nameAlg) {
812 case TPM2_ALG_SHA1:
813 hash_alg = "sha1";
814 break;
815 case TPM2_ALG_SHA256:
816 hash_alg = "sha256";
817 break;
818 default:
819 LOG_ERROR("Hash alg not implemented");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200820 return TSS2_ESYS_RC_BAD_VALUE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100821 }
Juergen Repp4a738892018-04-24 12:05:48 +0200822 switch (key->publicArea.parameters.rsaDetail.scheme.scheme) {
823 case TPM2_ALG_NULL:
824 padding = "raw";
Juergen Reppff821bd2017-12-11 15:21:42 +0100825 break;
Juergen Repp4a738892018-04-24 12:05:48 +0200826 case TPM2_ALG_RSAES:
827 padding = "pkcs1";
828 break;
829 case TPM2_ALG_OAEP:
830 padding = "oaep";
Juergen Reppff821bd2017-12-11 15:21:42 +0100831 break;
832 default:
Juergen Repp4a738892018-04-24 12:05:48 +0200833 LOG_ERROR("Illegal RSA scheme");
834 return TSS2_ESYS_RC_BAD_VALUE;
835 }
836 size_t offset = 0;
837 r = Tss2_MU_UINT32_Marshal(key->publicArea.parameters.rsaDetail.exponent,
838 &exponent[0], sizeof(UINT32), &offset);
839 if (r != TSS2_RC_SUCCESS) {
840 LOG_ERROR("Marsahling");
841 return r;
842 }
843 err = gcry_sexp_build(&sexp_data, NULL,
844 "(data (flags %s) (hash-algo %s) (label %b) (value %b) )",
845 padding, hash_alg, lsize, label, (int)in_size,
846 in_buffer);
847 if (err != GPG_ERR_NO_ERROR) {
848 LOG_ERROR("Function gcry_sexp_build");
849 return TSS2_ESYS_RC_GENERAL_FAILURE;
850 }
851 err = gcry_sexp_build(&sexp_key, NULL, "(public-key (rsa (n %b) (e %b)))",
852 (int)key->publicArea.unique.rsa.size,
853 &key->publicArea.unique.rsa.buffer[0], 4, exponent);
854 if (err != GPG_ERR_NO_ERROR) {
855 LOG_ERROR("Function gcry_sexp_build");
856 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100857 }
858 err = gcry_pk_encrypt(&sexp_cipher, sexp_data, sexp_key);
859 if (err != GPG_ERR_NO_ERROR) {
Juergen Repp4a738892018-04-24 12:05:48 +0200860 fprintf (stderr, "Failure: %s/%s\n",
861 gcry_strsource (err),
862 gcry_strerror (err));
Juergen Reppff821bd2017-12-11 15:21:42 +0100863 LOG_ERROR("Function gcry_pk_encrypt");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200864 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100865 }
866 sexp_cipher_a = gcry_sexp_find_token(sexp_cipher, "a", 0);
867 gcry_mpi_t mpi_cipher =
868 gcry_sexp_nth_mpi(sexp_cipher_a, 1, GCRYMPI_FMT_USG);
Juergen Reppff821bd2017-12-11 15:21:42 +0100869 err = gcry_mpi_print(GCRYMPI_FMT_USG, &out_buffer[0], max_out_size,
870 out_size, mpi_cipher);
871 if (err != GPG_ERR_NO_ERROR) {
872 LOG_ERROR("Function gcry_mpi_print");
Juergen Repp8fd96e42018-04-24 14:29:06 +0200873 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +0100874 }
875 free(sexp_data);
876 free(sexp_key);
877 free(sexp_cipher);
878 free(sexp_cipher_a);
879 return TSS2_RC_SUCCESS;
880}
881
Juergen Repp4a738892018-04-24 12:05:48 +0200882/** Computation of ephemeral ECC key and shared secret Z.
883 *
884 * According to the description in TPM spec part 1 C 6.1 a shared secret
885 * between application and TPM is computed (ECDH). An ephemeral ECC key and a
886 * TPM keyare used for the ECDH key exchange.
887 * @param[in] key The TPM key which will bu used for ECDH key exchange.
888 * @param[in] max_out_size the max size for the output of the public key of the
889 * computed ephemeral key.
890 * @param[out] Z The computed shared secret.
891 * @param[out] Q The public part of the ephemeral key in TPM format.
892 * @param[out] out_buffer The public part of the ephemeral key will be marshaled
893 * to this buffer.
894 * @param[out] out_size The size of the marshaled output.
895 */
896
897/*
898 * Format strings for some gcrypt sexps have to be created with sprintf due to
899 * a bug in libgcrypt. %s does not work in libgcypt with these sexps.
900 */
901#define SEXP_GENKEY_ECC "(genkey (ecc (curve %s)))"
902#define SEXP_ECC_POINT "(ecc (curve %s) (q.x %sb) (q.y %sb))"
903
904TSS2_RC
905iesys_cryptogcry_get_ecdh_point(TPM2B_PUBLIC *key,
906 size_t max_out_size,
907 TPM2B_ECC_PARAMETER *Z,
908 TPMS_ECC_POINT *Q,
909 BYTE * out_buffer,
910 size_t * out_size)
911{
912 TSS2_RC r;
913 gcry_error_t err;
914 char *curveId;
915 gcry_sexp_t mpi_tpm_sq = NULL; /* sexp for public part of TPM key*/
916 gcry_sexp_t mpi_sd = NULL; /* sexp for private part of ephemeral key */
917 gcry_sexp_t mpi_s_pub_q = NULL; /* sexp for public part of ephemeral key */
918 gcry_mpi_point_t mpi_q = NULL; /* public point of ephemeral key */
919 gcry_mpi_point_t mpi_tpm_q = NULL; /* public point of TPM key */
920 gcry_mpi_t mpi_d = NULL; /* private part of ephemeral key */
921 gcry_mpi_point_t mpi_qd = NULL; /* result of mpi_tpm_q * mpi_d */
922 gcry_ctx_t ctx = NULL; /* context for ec curves */
923 size_t size_x, size_y;
924 size_t offset = 0;
925 gcry_mpi_t mpi_x = gcry_mpi_new(521); /* big number for x coordinate */
926 gcry_mpi_t mpi_y = gcry_mpi_new(521); /* big number for y coordinate */
927
928 /* Set libcrypt constant fo curve type */
929 switch (key->publicArea.parameters.eccDetail.curveID) {
930 case TPM2_ECC_NIST_P192:
931 curveId = "\"NIST P-192\"";
932 break;
933 case TPM2_ECC_NIST_P224:
934 curveId = "\"NIST P-224\"";
935 break;
936 case TPM2_ECC_NIST_P256:
937 curveId = "\"NIST P-256\"";
938 break;
939 case TPM2_ECC_NIST_P384:
940 curveId = "\"NIST P-384\"";
941 break;
942 case TPM2_ECC_NIST_P521:
943 curveId = "\"NIST P-521\"";
944 break;
945 default:
946 LOG_ERROR("Illegal ECC curve ID");
947 return TSS2_ESYS_RC_BAD_VALUE;
948 }
949
950 /* compute ephemeral ecc key */
951 gcry_sexp_t ekey_spec = NULL, ekey_pair = NULL;
952 { /* scope for sexp_ecc_key */
953 char sexp_ecc_key [sizeof(SEXP_GENKEY_ECC)+strlen(curveId)
954 -1]; // -1 = (-2 for %s +1 for \0)
955
956 if (sprintf(&sexp_ecc_key[0], SEXP_GENKEY_ECC, curveId) < 1) {
957 goto_error(r, TSS2_ESYS_RC_MEMORY, "asprintf", cleanup);
958 }
959
960 if (gcry_sexp_build(&ekey_spec, NULL,
961 sexp_ecc_key) != GPG_ERR_NO_ERROR) {
962 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "gcry_sexp_build",
963 cleanup);
964 }
965 }
966
967 if (gcry_pk_genkey (&ekey_pair, ekey_spec) != GPG_ERR_NO_ERROR) {
968 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Create ephemeral ecc key",
969 cleanup);
970 }
971
972 /* Get private ephemeral key d */
973 mpi_sd = gcry_sexp_find_token(ekey_pair, "d", 0);
974 if (mpi_sd == NULL) {
975 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
976 "Get private part of ecc key", cleanup);
977 }
978 mpi_d = gcry_sexp_nth_mpi(mpi_sd, 1, GCRYMPI_FMT_USG);
979 if (mpi_d == NULL) {
980 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
981 "Get private part of ecc key from sexp", cleanup);
982 }
983
984 /* Construct ephemeral public key */
985 mpi_s_pub_q = gcry_sexp_find_token(ekey_pair, "public-key", 0);
986 if (mpi_s_pub_q == NULL) {
987 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get public part ecc key",
988 cleanup);
989 }
990
991 if (gcry_mpi_ec_new (&ctx, mpi_s_pub_q, curveId) != GPG_ERR_NO_ERROR) {
992 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Create ec", cleanup);
993 }
994 mpi_q = gcry_mpi_ec_get_point ("q", ctx, 1);
995 if (mpi_q == NULL) {
996 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get ecc point", cleanup);
997 }
998
999 /* Check whether point is on curve */
1000 if (!gcry_mpi_ec_curve_point(mpi_q, ctx)) {
1001 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Point not on curve",
1002 cleanup);
1003 }
1004
1005 /* Store ephemeral public key in Q */
1006 if (gcry_mpi_ec_get_affine (mpi_x, mpi_y, mpi_q, ctx)) {
1007 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Point is at infinity",
1008 cleanup);
1009 }
1010
1011 if (gcry_mpi_print(GCRYMPI_FMT_USG, &Q->x.buffer[0], max_out_size,
1012 &size_x, mpi_x) != GPG_ERR_NO_ERROR) {
1013 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get x part of point",
1014 cleanup);
1015 }
1016
1017 if (gcry_mpi_print(GCRYMPI_FMT_USG, &Q->y.buffer[0], max_out_size,
1018 &size_y, mpi_y) != GPG_ERR_NO_ERROR) {
1019 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Get y part of point",
1020 cleanup);
1021 }
1022 Q->x.size = size_x;
1023 Q->y.size = size_y;
1024 SAFE_FREE(ctx);
1025 { /* scope for sexp_point */
1026
1027 /* Get public point from TPM key */
1028 char sexp_point [sizeof(SEXP_ECC_POINT) + strlen(curveId)
1029 + key->publicArea.unique.ecc.x.size
1030 + key->publicArea.unique.ecc.y.size
1031 - 5]; /* -1 = (-4 for 2*%sb -2 for %s +1 for \0) */
1032
1033 if (sprintf(&sexp_point[0], SEXP_ECC_POINT,
1034 curveId, "%", "%") <1 ) {
1035 goto_error(r, TSS2_ESYS_RC_MEMORY, "asprintf", cleanup);
1036 }
1037
1038 err = gcry_sexp_build(&mpi_tpm_sq, NULL,
1039 sexp_point,
1040 key->publicArea.unique.ecc.x.size,
1041 &key->publicArea.unique.ecc.x.buffer[0],
1042 key->publicArea.unique.ecc.y.size,
1043 &key->publicArea.unique.ecc.y.buffer[0]);
1044 if (err != GPG_ERR_NO_ERROR) {
1045 LOG_ERROR("Function gcry_mpi_scan");
1046 return TSS2_ESYS_RC_GENERAL_FAILURE;
1047 }
1048 }
1049 offset = 0;
1050 r = Tss2_MU_TPMS_ECC_POINT_Marshal(Q, &out_buffer[0], max_out_size,
1051 &offset);
1052 return_if_error(r, "Error marshaling");
1053 *out_size = offset;
1054
1055 /* Multiply d and Q */
1056 if (gcry_mpi_ec_new (&ctx, mpi_tpm_sq, curveId) != GPG_ERR_NO_ERROR) {
1057 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "gcry_mpi_ec_new",
1058 cleanup);
1059 }
1060 mpi_tpm_q = gcry_mpi_ec_get_point ("q", ctx, 1);
1061 mpi_qd = gcry_mpi_point_new(256);
1062 gcry_mpi_ec_mul(mpi_qd , mpi_d, mpi_tpm_q, ctx);
1063
1064 /* Store the x coordinate of d*Q in Z which will be used for KDFe */
1065 if (gcry_mpi_ec_get_affine (mpi_x, mpi_y, mpi_qd, ctx)) {
1066 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE, "Point is at infinity",
1067 cleanup);
1068 }
1069
1070 if (gcry_mpi_print(GCRYMPI_FMT_USG, &Z->buffer[0], TPM2_MAX_ECC_KEY_BYTES,
1071 &size_x, mpi_x)) {
1072 goto_error(r, TSS2_ESYS_RC_GENERAL_FAILURE,
1073 "Get x coordinate d*Q", cleanup);
1074 }
1075
1076 Z->size = size_x;
1077 LOGBLOB_DEBUG(&Z->buffer[0], size_x, "Z (Q*d)");
1078
1079 cleanup:
1080 SAFE_FREE(ctx);
1081 SAFE_FREE(mpi_x);
1082 SAFE_FREE(mpi_y);
1083 SAFE_FREE(mpi_tpm_q);
1084 SAFE_FREE(mpi_qd);
1085 SAFE_FREE(mpi_q);
1086 SAFE_FREE(mpi_tpm_q);
1087 SAFE_FREE(mpi_tpm_sq);
1088 SAFE_FREE(ekey_spec);
1089 SAFE_FREE(mpi_s_pub_q);
1090
1091 return r;
1092}
1093
Juergen Reppff821bd2017-12-11 15:21:42 +01001094TSS2_RC
Juergen Reppff821bd2017-12-11 15:21:42 +01001095iesys_cryptogcry_sym_aes_init(gcry_cipher_hd_t * cipher_hd,
1096 uint8_t * key,
1097 TPM2_ALG_ID tpm_sym_alg,
1098 TPMI_AES_KEY_BITS key_bits,
1099 TPM2_ALG_ID tpm_mode,
Juergen Repp131e29f2018-04-24 14:43:39 +02001100 size_t iv_len, uint8_t * iv)
Juergen Reppff821bd2017-12-11 15:21:42 +01001101{
1102
1103 LOGBLOB_TRACE(key, (key_bits + 7) / 8, "IESYS AES key");
1104 LOGBLOB_TRACE(iv, iv_len, "IESYS AES iv");
1105 int algo, mode, len;
Juergen Reppff821bd2017-12-11 15:21:42 +01001106 size_t key_len = 0;
1107 gcry_error_t err;
1108 switch (tpm_sym_alg) {
1109 case TPM2_ALG_AES:
1110 switch (key_bits) {
1111 case 128:
1112 algo = GCRY_CIPHER_AES128;
1113 len = 128;
1114 break;
1115 case 192:
1116 algo = GCRY_CIPHER_AES192;
1117 len = 192;
1118 break;
1119 case 256:
1120 algo = GCRY_CIPHER_AES256;
1121 len = 256;
1122 break;
1123 default:
1124 LOG_ERROR("Illegal key length.");
Juergen Repp8fd96e42018-04-24 14:29:06 +02001125 return TSS2_ESYS_RC_BAD_VALUE;
Juergen Reppff821bd2017-12-11 15:21:42 +01001126 }
1127 switch (tpm_mode) {
1128 case TPM2_ALG_CBC:
1129 mode = GCRY_CIPHER_MODE_CBC;
1130 break;
1131 case TPM2_ALG_CFB:
1132 mode = GCRY_CIPHER_MODE_CFB;
1133 break;
1134 default:
1135 LOG_ERROR("Illegal symmetric algorithm.");
Juergen Repp8fd96e42018-04-24 14:29:06 +02001136 return TSS2_ESYS_RC_BAD_VALUE;
Juergen Reppff821bd2017-12-11 15:21:42 +01001137 }
1138 break;
1139 default:
1140 LOG_ERROR("Illegal symmetric algorithm.");
Juergen Repp8fd96e42018-04-24 14:29:06 +02001141 return TSS2_ESYS_RC_BAD_VALUE;
Juergen Reppff821bd2017-12-11 15:21:42 +01001142 }
1143 key_len = (len + 7) / 8;
1144 err = gcry_cipher_open(cipher_hd, algo, mode, 0);
1145 if (err != GPG_ERR_NO_ERROR) {
1146 LOG_ERROR("Opening gcrypt context");
Juergen Repp8fd96e42018-04-24 14:29:06 +02001147 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +01001148 }
1149 if (iv_len != 0) {
Juergen Repp131e29f2018-04-24 14:43:39 +02001150 err = gcry_cipher_setiv(*cipher_hd, &iv[0], iv_len);
Juergen Reppff821bd2017-12-11 15:21:42 +01001151 if (err != GPG_ERR_NO_ERROR) {
1152 LOG_ERROR("Function gcry_cipher_setiv");
Juergen Repp8fd96e42018-04-24 14:29:06 +02001153 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +01001154 }
1155 }
1156 err = gcry_cipher_setkey(*cipher_hd, key, key_len);
1157 if (err != GPG_ERR_NO_ERROR) {
1158 LOG_ERROR("Function gcry_cipher_setkey");
Juergen Repp8fd96e42018-04-24 14:29:06 +02001159 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +01001160 }
1161 return TSS2_RC_SUCCESS;
1162}
1163
1164TSS2_RC
1165iesys_cryptogcry_sym_aes_encrypt(uint8_t * key,
1166 TPM2_ALG_ID tpm_sym_alg,
1167 TPMI_AES_KEY_BITS key_bits,
1168 TPM2_ALG_ID tpm_mode,
1169 size_t blk_len,
1170 uint8_t * buffer,
1171 size_t buffer_size,
Juergen Repp131e29f2018-04-24 14:43:39 +02001172 uint8_t * iv)
Juergen Reppff821bd2017-12-11 15:21:42 +01001173{
1174 gcry_cipher_hd_t cipher_hd;
Juergen Reppff821bd2017-12-11 15:21:42 +01001175 gcry_error_t err;
1176 TSS2_RC r;
Juergen Repp131e29f2018-04-24 14:43:39 +02001177
1178 if (key == NULL || buffer == NULL) {
1179 LOG_ERROR("Bad reference");
1180 return TSS2_ESYS_RC_BAD_REFERENCE;
1181 }
1182
Juergen Reppff821bd2017-12-11 15:21:42 +01001183 r = iesys_cryptogcry_sym_aes_init(&cipher_hd, key, tpm_sym_alg,
Juergen Repp131e29f2018-04-24 14:43:39 +02001184 key_bits, tpm_mode, blk_len, iv);
Juergen Reppff821bd2017-12-11 15:21:42 +01001185 if (r != TSS2_RC_SUCCESS)
1186 return r;
1187 LOGBLOB_TRACE(buffer, buffer_size, "IESYS AES input");
1188 err = gcry_cipher_encrypt(cipher_hd, buffer, buffer_size, NULL, 0);
1189 LOGBLOB_TRACE(buffer, buffer_size, "IESYS AES output");
1190 if (err != GPG_ERR_NO_ERROR) {
1191 LOG_ERROR("Function gcry_cipher_encrypt");
Juergen Repp8fd96e42018-04-24 14:29:06 +02001192 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +01001193 }
1194 gcry_cipher_close(cipher_hd);
1195 return TSS2_RC_SUCCESS;
1196}
1197
1198TSS2_RC
1199iesys_cryptogcry_sym_aes_decrypt(uint8_t * key,
1200 TPM2_ALG_ID tpm_sym_alg,
1201 TPMI_AES_KEY_BITS key_bits,
1202 TPM2_ALG_ID tpm_mode,
1203 size_t blk_len,
Juergen Repp131e29f2018-04-24 14:43:39 +02001204 uint8_t * buffer,
1205 size_t buffer_size,
1206 uint8_t * iv)
Juergen Reppff821bd2017-12-11 15:21:42 +01001207{
1208 gcry_cipher_hd_t cipher_hd;
Juergen Reppff821bd2017-12-11 15:21:42 +01001209 gcry_error_t err;
1210 TSS2_RC r;
Juergen Repp8fd96e42018-04-24 14:29:06 +02001211
1212 if (tpm_sym_alg != TPM2_ALG_AES) {
1213 LOG_ERROR("AES expected");
1214 return TSS2_ESYS_RC_GENERAL_FAILURE;
1215 }
1216
1217 if (key == NULL || buffer == NULL) {
1218 LOG_ERROR("Bad reference");
1219 return TSS2_ESYS_RC_BAD_REFERENCE;
1220 }
1221
Juergen Reppff821bd2017-12-11 15:21:42 +01001222 r = iesys_cryptogcry_sym_aes_init(&cipher_hd, key, tpm_sym_alg,
Juergen Repp131e29f2018-04-24 14:43:39 +02001223 key_bits, tpm_mode, blk_len, iv);
Juergen Reppff821bd2017-12-11 15:21:42 +01001224 if (r != TSS2_RC_SUCCESS)
1225 return r;
1226 err = gcry_cipher_decrypt(cipher_hd, buffer, buffer_size, NULL, 0);
1227 if (err != GPG_ERR_NO_ERROR) {
1228 LOG_ERROR("Function gcry_cipher_decrypt");
Juergen Repp8fd96e42018-04-24 14:29:06 +02001229 return TSS2_ESYS_RC_GENERAL_FAILURE;
Juergen Reppff821bd2017-12-11 15:21:42 +01001230 }
1231 gcry_cipher_close(cipher_hd);
1232 return TSS2_RC_SUCCESS;
1233}
Juergen Reppf29cfef2018-03-27 14:18:07 +02001234
1235
1236TSS2_RC
1237iesys_xor_parameter_obfuscation(TPM2_ALG_ID hash_alg,
1238 uint8_t *key,
1239 size_t key_size,
1240 TPM2B_NONCE * contextU,
1241 TPM2B_NONCE * contextV,
1242 BYTE *data,
1243 size_t data_size)
1244{
1245 TSS2_RC r;
1246 uint32_t counter = 0;
1247 BYTE kdfa_result[TPM2_MAX_DIGEST_BUFFER];
1248 size_t digest_size;
1249 size_t data_size_bits = data_size * 8;
1250 size_t rest_size = data_size;
1251 BYTE *kdfa_byte_ptr;
Juergen Repp8fd96e42018-04-24 14:29:06 +02001252
1253 if (key == NULL || data == NULL) {
1254 LOG_ERROR("Bad reference");
1255 return TSS2_ESYS_RC_BAD_REFERENCE;
1256 }
1257
Juergen Reppf29cfef2018-03-27 14:18:07 +02001258 r = iesys_crypto_hash_get_digest_size(hash_alg, &digest_size);
1259 return_if_error(r, "Hash alg not supported");
1260 while(rest_size > 0) {
1261 r = iesys_crypto_KDFa(hash_alg, key, key_size, "XOR",
1262 contextU, contextV, data_size_bits, &counter,
1263 kdfa_result, TRUE);
1264 return_if_error(r, "iesys_crypto_KDFa failed");
1265 /* XOR next data sub block with KDFa result */
1266 kdfa_byte_ptr = kdfa_result;
1267 LOGBLOB_TRACE(data, data_size, "Parameter data before XOR");
1268 for(size_t i = digest_size < rest_size ? digest_size : rest_size; i > 0;
1269 i--)
1270 *data++ ^= *kdfa_byte_ptr++;
1271 LOGBLOB_TRACE(data, data_size, "Parameter data after XOR");
1272 rest_size = rest_size < digest_size ? 0 : rest_size - digest_size;
1273 }
1274 return TSS2_RC_SUCCESS;
1275}