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. 2007
8 *
9 */
10
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <string.h>
16
17 #include "trousers/tss.h"
18 #include "trousers/trousers.h"
19 #include "trousers_types.h"
20 #include "spi_utils.h"
21 #include "capabilities.h"
22 #include "tsplog.h"
23 #include "obj.h"
24
25
26 void
migdata_free(void * data)27 migdata_free(void *data)
28 {
29 struct tr_migdata_obj *migdata = (struct tr_migdata_obj *)data;
30
31 free(migdata);
32 }
33
34 TSS_BOOL
obj_is_migdata(TSS_HOBJECT hObject)35 obj_is_migdata(TSS_HOBJECT hObject)
36 {
37 TSS_BOOL answer = FALSE;
38
39 if ((obj_list_get_obj(&migdata_list, hObject))) {
40 answer = TRUE;
41 obj_list_put(&migdata_list);
42 }
43
44 return answer;
45 }
46
47 TSS_RESULT
obj_migdata_add(TSS_HCONTEXT hContext,TSS_HOBJECT * phObject)48 obj_migdata_add(TSS_HCONTEXT hContext, TSS_HOBJECT *phObject)
49 {
50 TSS_RESULT result;
51 struct tr_migdata_obj *migdata = calloc(1, sizeof(struct tr_migdata_obj));
52
53 if (migdata == NULL) {
54 LogError("malloc of %zd bytes failed.", sizeof(struct tr_migdata_obj));
55 return TSPERR(TSS_E_OUTOFMEMORY);
56 }
57
58 if ((result = obj_list_add(&migdata_list, hContext, 0, migdata, phObject))) {
59 free(migdata);
60 return result;
61 }
62
63 return TSS_SUCCESS;
64 }
65
66 TSS_RESULT
obj_migdata_remove(TSS_HMIGDATA hMigData,TSS_HCONTEXT hContext)67 obj_migdata_remove(TSS_HMIGDATA hMigData, TSS_HCONTEXT hContext)
68 {
69 TSS_RESULT result;
70
71 if ((result = obj_list_remove(&migdata_list, &migdata_free, hMigData, hContext)))
72 return result;
73
74 return TSS_SUCCESS;
75 }
76
77 TSS_RESULT
obj_migdata_get_tsp_context(TSS_HMIGDATA hMigData,TSS_HCONTEXT * hContext)78 obj_migdata_get_tsp_context(TSS_HMIGDATA hMigData, TSS_HCONTEXT *hContext)
79 {
80 struct tsp_object *obj;
81
82 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
83 return TSPERR(TSS_E_INVALID_HANDLE);
84
85 *hContext = obj->tspContext;
86
87 obj_list_put(&migdata_list);
88
89 return TSS_SUCCESS;
90 }
91
92 TSS_RESULT
obj_migdata_set_migrationblob(TSS_HMIGDATA hMigData,UINT32 whichOne,UINT32 blobSize,BYTE * blob)93 obj_migdata_set_migrationblob(TSS_HMIGDATA hMigData, UINT32 whichOne, UINT32 blobSize, BYTE *blob)
94 {
95 TSS_RESULT result;
96
97 switch (whichOne) {
98 case TSS_MIGATTRIB_MIG_MSALIST_PUBKEY_BLOB:
99 result = obj_migdata_set_msa_pubkey(hMigData, blobSize, blob);
100 break;
101 case TSS_MIGATTRIB_MIG_AUTHORITY_PUBKEY_BLOB:
102 result = obj_migdata_set_ma_pubkey(hMigData, blobSize, blob);
103 break;
104 case TSS_MIGATTRIB_MIG_DESTINATION_PUBKEY_BLOB:
105 result = obj_migdata_set_dest_pubkey(hMigData, blobSize, blob);
106 break;
107 case TSS_MIGATTRIB_MIG_SOURCE_PUBKEY_BLOB:
108 result = obj_migdata_set_src_pubkey(hMigData, blobSize, blob);
109 break;
110 default:
111 result = TSPERR(TSS_E_BAD_PARAMETER);
112 }
113
114 return result;
115 }
116
117 TSS_RESULT
obj_migdata_get_migrationblob(TSS_HMIGDATA hMigData,UINT32 whichOne,UINT32 * blobSize,BYTE ** blob)118 obj_migdata_get_migrationblob(TSS_HMIGDATA hMigData, UINT32 whichOne, UINT32 *blobSize, BYTE **blob)
119 {
120 TSS_RESULT result;
121
122 switch (whichOne) {
123 case TSS_MIGATTRIB_MIG_XOR_BLOB:
124 result = obj_migdata_get_blob(hMigData, blobSize, blob);
125 break;
126 default:
127 result = TSPERR(TSS_E_BAD_PARAMETER);
128 }
129
130 return result;
131 }
132
133 TSS_RESULT
obj_migdata_set_authoritydata(TSS_HMIGDATA hMigData,UINT32 whichOne,UINT32 blobSize,BYTE * blob)134 obj_migdata_set_authoritydata(TSS_HMIGDATA hMigData, UINT32 whichOne, UINT32 blobSize, BYTE *blob)
135 {
136 TSS_RESULT result;
137
138 switch (whichOne) {
139 case TSS_MIGATTRIB_AUTHORITY_DIGEST:
140 result = obj_migdata_set_msa_digest(hMigData, blobSize, blob);
141 break;
142 case TSS_MIGATTRIB_AUTHORITY_APPROVAL_HMAC:
143 result = obj_migdata_set_msa_hmac(hMigData, blobSize, blob);
144 break;
145 case TSS_MIGATTRIB_AUTHORITY_MSALIST:
146 result = obj_migdata_set_msa_list(hMigData, blobSize, blob);
147 break;
148 default:
149 result = TSPERR(TSS_E_BAD_PARAMETER);
150 }
151
152 return result;
153 }
154
155 TSS_RESULT
obj_migdata_get_authoritydata(TSS_HMIGDATA hMigData,UINT32 whichOne,UINT32 * blobSize,BYTE ** blob)156 obj_migdata_get_authoritydata(TSS_HMIGDATA hMigData, UINT32 whichOne, UINT32 *blobSize, BYTE **blob)
157 {
158 TSS_RESULT result;
159
160 switch (whichOne) {
161 case TSS_MIGATTRIB_AUTHORITY_DIGEST:
162 result = obj_migdata_get_msa_digest(hMigData, blobSize, blob);
163 break;
164 case TSS_MIGATTRIB_AUTHORITY_APPROVAL_HMAC:
165 result = obj_migdata_get_msa_hmac(hMigData, blobSize, blob);
166 break;
167 case TSS_MIGATTRIB_AUTHORITY_MSALIST:
168 result = obj_migdata_get_msa_list(hMigData, blobSize, blob);
169 break;
170 default:
171 result = TSPERR(TSS_E_BAD_PARAMETER);
172 }
173
174 return result;
175 }
176
177 TSS_RESULT
obj_migdata_set_migauthdata(TSS_HMIGDATA hMigData,UINT32 whichOne,UINT32 blobSize,BYTE * blob)178 obj_migdata_set_migauthdata(TSS_HMIGDATA hMigData, UINT32 whichOne, UINT32 blobSize, BYTE *blob)
179 {
180 TSS_RESULT result;
181
182 switch (whichOne) {
183 case TSS_MIGATTRIB_MIG_AUTH_AUTHORITY_DIGEST:
184 result = obj_migdata_set_ma_digest(hMigData, blobSize, blob);
185 break;
186 case TSS_MIGATTRIB_MIG_AUTH_DESTINATION_DIGEST:
187 result = obj_migdata_set_dest_digest(hMigData, blobSize, blob);
188 break;
189 case TSS_MIGATTRIB_MIG_AUTH_SOURCE_DIGEST:
190 result = obj_migdata_set_src_digest(hMigData, blobSize, blob);
191 break;
192 default:
193 result = TSPERR(TSS_E_BAD_PARAMETER);
194 }
195
196 return result;
197 }
198
199 TSS_RESULT
obj_migdata_get_migauthdata(TSS_HMIGDATA hMigData,UINT32 whichOne,UINT32 * blobSize,BYTE ** blob)200 obj_migdata_get_migauthdata(TSS_HMIGDATA hMigData, UINT32 whichOne, UINT32 *blobSize, BYTE **blob)
201 {
202 TSS_RESULT result;
203
204 switch (whichOne) {
205 case TSS_MIGATTRIB_MIG_AUTH_AUTHORITY_DIGEST:
206 result = obj_migdata_get_ma_digest(hMigData, blobSize, blob);
207 break;
208 case TSS_MIGATTRIB_MIG_AUTH_DESTINATION_DIGEST:
209 result = obj_migdata_get_dest_digest(hMigData, blobSize, blob);
210 break;
211 case TSS_MIGATTRIB_MIG_AUTH_SOURCE_DIGEST:
212 result = obj_migdata_get_src_digest(hMigData, blobSize, blob);
213 break;
214 default:
215 result = TSPERR(TSS_E_BAD_PARAMETER);
216 }
217
218 return result;
219 }
220
221 TSS_RESULT
obj_migdata_set_ticketdata(TSS_HMIGDATA hMigData,UINT32 whichOne,UINT32 blobSize,BYTE * blob)222 obj_migdata_set_ticketdata(TSS_HMIGDATA hMigData, UINT32 whichOne, UINT32 blobSize, BYTE *blob)
223 {
224 TSS_RESULT result;
225
226 switch (whichOne) {
227 case TSS_MIGATTRIB_TICKET_SIG_DIGEST:
228 result = obj_migdata_set_sig_data(hMigData, blobSize, blob);
229 break;
230 case TSS_MIGATTRIB_TICKET_SIG_VALUE:
231 result = obj_migdata_set_sig_value(hMigData, blobSize, blob);
232 break;
233 case TSS_MIGATTRIB_TICKET_SIG_TICKET:
234 result = obj_migdata_set_sig_ticket(hMigData, blobSize, blob);
235 break;
236 case TSS_MIGATTRIB_TICKET_RESTRICT_TICKET:
237 result = obj_migdata_set_cmk_auth(hMigData, blobSize, blob);
238 break;
239 default:
240 result = TSPERR(TSS_E_BAD_PARAMETER);
241 }
242
243 return result;
244 }
245
246 TSS_RESULT
obj_migdata_get_ticketdata(TSS_HMIGDATA hMigData,UINT32 whichOne,UINT32 * blobSize,BYTE ** blob)247 obj_migdata_get_ticketdata(TSS_HMIGDATA hMigData, UINT32 whichOne, UINT32 *blobSize, BYTE **blob)
248 {
249 TSS_RESULT result;
250
251 switch (whichOne) {
252 case TSS_MIGATTRIB_TICKET_SIG_TICKET:
253 result = obj_migdata_get_sig_ticket(hMigData, blobSize, blob);
254 break;
255 default:
256 result = TSPERR(TSS_E_BAD_PARAMETER);
257 }
258
259 return result;
260 }
261
262 TSS_RESULT
obj_migdata_set_ticket_blob(TSS_HMIGDATA hMigData,UINT32 migTicketSize,BYTE * migTicket)263 obj_migdata_set_ticket_blob(TSS_HMIGDATA hMigData, UINT32 migTicketSize, BYTE *migTicket)
264 {
265 struct tsp_object *obj;
266 struct tr_migdata_obj *migdata;
267 TSS_RESULT result = TSS_SUCCESS;
268
269 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
270 return TSPERR(TSS_E_INVALID_HANDLE);
271
272 migdata = (struct tr_migdata_obj *)obj->data;
273
274 migdata->migTicketSize = 0;
275 free(migdata->migTicket);
276 if ((migdata->migTicket = malloc(migTicketSize)) == NULL) {
277 LogError("malloc of %u bytes failed.", migTicketSize);
278 result = TSPERR(TSS_E_OUTOFMEMORY);
279 goto done;
280 }
281 memcpy(migdata->migTicket, migTicket, migTicketSize);
282 migdata->migTicketSize = migTicketSize;
283
284 done:
285 obj_list_put(&migdata_list);
286
287 return result;
288 }
289
290 TSS_RESULT
obj_migdata_get_ticket_blob(TSS_HMIGDATA hMigData,UINT32 * migTicketSize,BYTE ** migTicket)291 obj_migdata_get_ticket_blob(TSS_HMIGDATA hMigData, UINT32 *migTicketSize, BYTE **migTicket)
292 {
293 struct tsp_object *obj;
294 struct tr_migdata_obj *migdata;
295 TSS_RESULT result = TSS_SUCCESS;
296
297 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
298 return TSPERR(TSS_E_INVALID_HANDLE);
299
300 migdata = (struct tr_migdata_obj *)obj->data;
301
302 if ((*migTicket = calloc_tspi(obj->tspContext, migdata->migTicketSize)) == NULL) {
303 LogError("malloc of %u bytes failed.", migdata->migTicketSize);
304 result = TSPERR(TSS_E_OUTOFMEMORY);
305 goto done;
306 }
307 memcpy(*migTicket, migdata->migTicket, migdata->migTicketSize);
308 *migTicketSize = migdata->migTicketSize;
309
310 done:
311 obj_list_put(&migdata_list);
312
313 return result;
314 }
315
316 TSS_RESULT
obj_migdata_set_msa_list(TSS_HMIGDATA hMigData,UINT32 msaListSize,BYTE * msaList)317 obj_migdata_set_msa_list(TSS_HMIGDATA hMigData, UINT32 msaListSize, BYTE *msaList)
318 {
319 struct tsp_object *obj;
320 struct tr_migdata_obj *migdata;
321 UINT32 i, count, size;
322 TPM_DIGEST *digest;
323 TSS_RESULT result = TSS_SUCCESS;
324
325 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
326 return TSPERR(TSS_E_INVALID_HANDLE);
327
328 migdata = (struct tr_migdata_obj *)obj->data;
329
330 count = msaListSize / sizeof(digest->digest);
331 size = count * sizeof(*digest);
332
333 migdata->msaList.MSAlist = 0;
334 free(migdata->msaList.migAuthDigest);
335 if ((migdata->msaList.migAuthDigest = malloc(size)) == NULL) {
336 LogError("malloc of %u bytes failed.", size);
337 result = TSPERR(TSS_E_OUTOFMEMORY);
338 goto done;
339 }
340 digest = migdata->msaList.migAuthDigest;
341 for (i = 0; i < count; i++) {
342 memcpy(digest->digest, msaList, sizeof(digest->digest));
343 msaList += sizeof(digest->digest);
344 digest++;
345 }
346 migdata->msaList.MSAlist = count;
347
348 result = obj_migdata_calc_msa_digest(migdata);
349
350 done:
351 obj_list_put(&migdata_list);
352
353 return result;
354 }
355
356 TSS_RESULT
obj_migdata_get_msa_list(TSS_HMIGDATA hMigData,UINT32 * size,BYTE ** msaList)357 obj_migdata_get_msa_list(TSS_HMIGDATA hMigData, UINT32 *size, BYTE **msaList)
358 {
359 struct tsp_object *obj;
360 struct tr_migdata_obj *migdata;
361 UINT32 i;
362 TPM_DIGEST *digest;
363 BYTE *tmpMsaList;
364 TSS_RESULT result = TSS_SUCCESS;
365
366 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
367 return TSPERR(TSS_E_INVALID_HANDLE);
368
369 migdata = (struct tr_migdata_obj *)obj->data;
370
371 *size = migdata->msaList.MSAlist * sizeof(migdata->msaList.migAuthDigest->digest);
372 if ((*msaList = calloc_tspi(obj->tspContext, *size)) == NULL) {
373 LogError("malloc of %u bytes failed.", *size);
374 result = TSPERR(TSS_E_OUTOFMEMORY);
375 goto done;
376 }
377 tmpMsaList = *msaList;
378 digest = migdata->msaList.migAuthDigest;
379 for (i = 0; i < migdata->msaList.MSAlist; i++) {
380 memcpy(tmpMsaList, digest->digest, sizeof(digest->digest));
381 tmpMsaList += sizeof(digest->digest);
382 digest++;
383 }
384
385 done:
386 obj_list_put(&migdata_list);
387
388 return result;
389 }
390
391 TSS_RESULT
obj_migdata_set_msa_pubkey(TSS_HMIGDATA hMigData,UINT32 blobSize,BYTE * pubKeyBlob)392 obj_migdata_set_msa_pubkey(TSS_HMIGDATA hMigData, UINT32 blobSize, BYTE *pubKeyBlob)
393 {
394 struct tsp_object *obj;
395 struct tr_migdata_obj *migdata;
396 UINT32 size;
397 TPM_DIGEST msaDigest;
398 TPM_DIGEST *digest;
399 TSS_RESULT result = TSS_SUCCESS;
400
401 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
402 return TSPERR(TSS_E_INVALID_HANDLE);
403
404 migdata = (struct tr_migdata_obj *)obj->data;
405
406 if ((result = obj_migdata_calc_pubkey_digest(blobSize, pubKeyBlob, &msaDigest)))
407 goto done;
408
409 size = (migdata->msaList.MSAlist + 1) * sizeof(*digest);
410 if ((migdata->msaList.migAuthDigest = realloc(migdata->msaList.migAuthDigest, size)) == NULL) {
411 LogError("malloc of %u bytes failed.", size);
412 result = TSPERR(TSS_E_OUTOFMEMORY);
413 goto done;
414 }
415 digest = migdata->msaList.migAuthDigest + migdata->msaList.MSAlist;
416 *digest = msaDigest;
417 migdata->msaList.MSAlist++;
418
419 result = obj_migdata_calc_msa_digest(migdata);
420
421 done:
422 obj_list_put(&migdata_list);
423
424 return result;
425 }
426
427 TSS_RESULT
obj_migdata_set_msa_digest(TSS_HMIGDATA hMigData,UINT32 digestSize,BYTE * digest)428 obj_migdata_set_msa_digest(TSS_HMIGDATA hMigData, UINT32 digestSize, BYTE *digest)
429 {
430 struct tsp_object *obj;
431 struct tr_migdata_obj *migdata;
432 TSS_RESULT result = TSS_SUCCESS;
433
434 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
435 return TSPERR(TSS_E_INVALID_HANDLE);
436
437 migdata = (struct tr_migdata_obj *)obj->data;
438
439 if (digestSize != sizeof(migdata->msaDigest.digest)) {
440 result = TSPERR(TSS_E_BAD_PARAMETER);
441 goto done;
442 }
443 memcpy(migdata->msaDigest.digest, digest, sizeof(migdata->msaDigest.digest));
444
445 done:
446 obj_list_put(&migdata_list);
447
448 return result;
449 }
450
451 TSS_RESULT
obj_migdata_get_msa_digest(TSS_HMIGDATA hMigData,UINT32 * digestSize,BYTE ** digest)452 obj_migdata_get_msa_digest(TSS_HMIGDATA hMigData, UINT32 *digestSize, BYTE **digest)
453 {
454 struct tsp_object *obj;
455 struct tr_migdata_obj *migdata;
456 TSS_RESULT result = TSS_SUCCESS;
457
458 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
459 return TSPERR(TSS_E_INVALID_HANDLE);
460
461 migdata = (struct tr_migdata_obj *)obj->data;
462
463 if ((*digest = calloc_tspi(obj->tspContext, sizeof(migdata->msaDigest.digest))) == NULL) {
464 LogError("malloc of %zd bytes failed.", sizeof(migdata->msaDigest.digest));
465 result = TSPERR(TSS_E_OUTOFMEMORY);
466 goto done;
467 }
468 memcpy(*digest, migdata->msaDigest.digest, sizeof(migdata->msaDigest.digest));
469 *digestSize = sizeof(migdata->msaDigest.digest);
470
471 done:
472 obj_list_put(&migdata_list);
473
474 return result;
475 }
476
477 TSS_RESULT
obj_migdata_get_msa_list_blob(TSS_HMIGDATA hMigData,UINT32 * blobSize,BYTE ** msaListBlob)478 obj_migdata_get_msa_list_blob(TSS_HMIGDATA hMigData, UINT32 *blobSize, BYTE **msaListBlob)
479 {
480 struct tsp_object *obj;
481 struct tr_migdata_obj *migdata;
482 UINT64 offset;
483 TSS_RESULT result = TSS_SUCCESS;
484
485 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
486 return TSPERR(TSS_E_INVALID_HANDLE);
487
488 migdata = (struct tr_migdata_obj *)obj->data;
489
490 offset = 0;
491 Trspi_LoadBlob_MSA_COMPOSITE(&offset, NULL, &migdata->msaList);
492
493 *blobSize = offset;
494 if ((*msaListBlob = calloc_tspi(obj->tspContext, *blobSize)) == NULL) {
495 LogError("malloc of %u bytes failed.", *blobSize);
496 result = TSPERR(TSS_E_OUTOFMEMORY);
497 goto done;
498 }
499 offset = 0;
500 Trspi_LoadBlob_MSA_COMPOSITE(&offset, *msaListBlob, &migdata->msaList);
501
502 done:
503 obj_list_put(&migdata_list);
504
505 return result;
506 }
507
508 TSS_RESULT
obj_migdata_set_msa_hmac(TSS_HMIGDATA hMigData,UINT32 hmacSize,BYTE * hmac)509 obj_migdata_set_msa_hmac(TSS_HMIGDATA hMigData, UINT32 hmacSize, BYTE *hmac)
510 {
511 struct tsp_object *obj;
512 struct tr_migdata_obj *migdata;
513 TSS_RESULT result = TSS_SUCCESS;
514
515 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
516 return TSPERR(TSS_E_INVALID_HANDLE);
517
518 migdata = (struct tr_migdata_obj *)obj->data;
519
520 if (hmacSize != sizeof(migdata->msaHmac.digest)) {
521 result = TSPERR(TSS_E_BAD_PARAMETER);
522 goto done;
523 }
524 memcpy(migdata->msaHmac.digest, hmac, sizeof(migdata->msaHmac.digest));
525
526 done:
527 obj_list_put(&migdata_list);
528
529 return result;
530 }
531
532 TSS_RESULT
obj_migdata_get_msa_hmac(TSS_HMIGDATA hMigData,UINT32 * hmacSize,BYTE ** hmac)533 obj_migdata_get_msa_hmac(TSS_HMIGDATA hMigData, UINT32 *hmacSize, BYTE **hmac)
534 {
535 struct tsp_object *obj;
536 struct tr_migdata_obj *migdata;
537 TSS_RESULT result = TSS_SUCCESS;
538
539 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
540 return TSPERR(TSS_E_INVALID_HANDLE);
541
542 migdata = (struct tr_migdata_obj *)obj->data;
543
544 if ((*hmac = calloc_tspi(obj->tspContext, sizeof(migdata->msaHmac.digest))) == NULL) {
545 LogError("malloc of %zd bytes failed.", sizeof(migdata->msaHmac.digest));
546 result = TSPERR(TSS_E_OUTOFMEMORY);
547 goto done;
548 }
549 memcpy(*hmac, migdata->msaHmac.digest, sizeof(migdata->msaHmac.digest));
550 *hmacSize = sizeof(migdata->msaHmac.digest);
551
552 done:
553 obj_list_put(&migdata_list);
554
555 return result;
556 }
557
558 TSS_RESULT
obj_migdata_set_ma_pubkey(TSS_HMIGDATA hMigData,UINT32 blobSize,BYTE * pubKeyBlob)559 obj_migdata_set_ma_pubkey(TSS_HMIGDATA hMigData, UINT32 blobSize, BYTE *pubKeyBlob)
560 {
561 struct tsp_object *obj;
562 struct tr_migdata_obj *migdata;
563 TPM_DIGEST pubKeyDigest;
564 TSS_RESULT result = TSS_SUCCESS;
565
566 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
567 return TSPERR(TSS_E_INVALID_HANDLE);
568
569 migdata = (struct tr_migdata_obj *)obj->data;
570
571 if ((result = obj_migdata_calc_pubkey_digest(blobSize, pubKeyBlob, &pubKeyDigest)))
572 goto done;
573
574 migdata->maDigest = pubKeyDigest;
575
576 obj_migdata_calc_sig_data_digest(migdata);
577
578 done:
579 obj_list_put(&migdata_list);
580
581 return result;
582 }
583
584 TSS_RESULT
obj_migdata_set_ma_digest(TSS_HMIGDATA hMigData,UINT32 digestSize,BYTE * digest)585 obj_migdata_set_ma_digest(TSS_HMIGDATA hMigData, UINT32 digestSize, BYTE *digest)
586 {
587 struct tsp_object *obj;
588 struct tr_migdata_obj *migdata;
589 TSS_RESULT result = TSS_SUCCESS;
590
591 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
592 return TSPERR(TSS_E_INVALID_HANDLE);
593
594 migdata = (struct tr_migdata_obj *)obj->data;
595
596 if (digestSize != sizeof(migdata->maDigest.digest)) {
597 result = TSPERR(TSS_E_BAD_PARAMETER);
598 goto done;
599 }
600 memcpy(migdata->maDigest.digest, digest, sizeof(migdata->maDigest.digest));
601
602 obj_migdata_calc_sig_data_digest(migdata);
603
604 done:
605 obj_list_put(&migdata_list);
606
607 return result;
608 }
609
610 TSS_RESULT
obj_migdata_get_ma_digest(TSS_HMIGDATA hMigData,UINT32 * digestSize,BYTE ** digest)611 obj_migdata_get_ma_digest(TSS_HMIGDATA hMigData, UINT32 *digestSize, BYTE **digest)
612 {
613 struct tsp_object *obj;
614 struct tr_migdata_obj *migdata;
615 TSS_RESULT result = TSS_SUCCESS;
616
617 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
618 return TSPERR(TSS_E_INVALID_HANDLE);
619
620 migdata = (struct tr_migdata_obj *)obj->data;
621
622 if ((*digest = calloc_tspi(obj->tspContext, sizeof(migdata->maDigest.digest))) == NULL) {
623 LogError("malloc of %zd bytes failed.", sizeof(migdata->maDigest.digest));
624 result = TSPERR(TSS_E_OUTOFMEMORY);
625 goto done;
626 }
627 memcpy(*digest, migdata->maDigest.digest, sizeof(migdata->maDigest.digest));
628 *digestSize = sizeof(migdata->maDigest.digest);
629
630 done:
631 obj_list_put(&migdata_list);
632
633 return result;
634 }
635
636 TSS_RESULT
obj_migdata_set_dest_pubkey(TSS_HMIGDATA hMigData,UINT32 blobSize,BYTE * pubKeyBlob)637 obj_migdata_set_dest_pubkey(TSS_HMIGDATA hMigData, UINT32 blobSize, BYTE *pubKeyBlob)
638 {
639 struct tsp_object *obj;
640 struct tr_migdata_obj *migdata;
641 TPM_DIGEST pubKeyDigest;
642 TSS_RESULT result = TSS_SUCCESS;
643
644 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
645 return TSPERR(TSS_E_INVALID_HANDLE);
646
647 migdata = (struct tr_migdata_obj *)obj->data;
648
649 if ((result = obj_migdata_calc_pubkey_digest(blobSize, pubKeyBlob, &pubKeyDigest)))
650 goto done;
651
652 migdata->destDigest = pubKeyDigest;
653
654 obj_migdata_calc_sig_data_digest(migdata);
655
656 done:
657 obj_list_put(&migdata_list);
658
659 return result;
660 }
661
662 TSS_RESULT
obj_migdata_set_dest_digest(TSS_HMIGDATA hMigData,UINT32 digestSize,BYTE * digest)663 obj_migdata_set_dest_digest(TSS_HMIGDATA hMigData, UINT32 digestSize, BYTE *digest)
664 {
665 struct tsp_object *obj;
666 struct tr_migdata_obj *migdata;
667 TSS_RESULT result = TSS_SUCCESS;
668
669 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
670 return TSPERR(TSS_E_INVALID_HANDLE);
671
672 migdata = (struct tr_migdata_obj *)obj->data;
673
674 if (digestSize != sizeof(migdata->destDigest.digest)) {
675 result = TSPERR(TSS_E_BAD_PARAMETER);
676 goto done;
677 }
678 memcpy(migdata->destDigest.digest, digest, sizeof(migdata->destDigest.digest));
679
680 obj_migdata_calc_sig_data_digest(migdata);
681
682 done:
683 obj_list_put(&migdata_list);
684
685 return result;
686 }
687
688 TSS_RESULT
obj_migdata_get_dest_digest(TSS_HMIGDATA hMigData,UINT32 * digestSize,BYTE ** digest)689 obj_migdata_get_dest_digest(TSS_HMIGDATA hMigData, UINT32 *digestSize, BYTE **digest)
690 {
691 struct tsp_object *obj;
692 struct tr_migdata_obj *migdata;
693 TSS_RESULT result = TSS_SUCCESS;
694
695 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
696 return TSPERR(TSS_E_INVALID_HANDLE);
697
698 migdata = (struct tr_migdata_obj *)obj->data;
699
700 if ((*digest = calloc_tspi(obj->tspContext, sizeof(migdata->destDigest.digest))) == NULL) {
701 LogError("malloc of %zd bytes failed.", sizeof(migdata->destDigest.digest));
702 result = TSPERR(TSS_E_OUTOFMEMORY);
703 goto done;
704 }
705 memcpy(*digest, migdata->destDigest.digest, sizeof(migdata->destDigest.digest));
706 *digestSize = sizeof(migdata->destDigest.digest);
707
708 done:
709 obj_list_put(&migdata_list);
710
711 return result;
712 }
713
714 TSS_RESULT
obj_migdata_set_src_pubkey(TSS_HMIGDATA hMigData,UINT32 blobSize,BYTE * pubKeyBlob)715 obj_migdata_set_src_pubkey(TSS_HMIGDATA hMigData, UINT32 blobSize, BYTE *pubKeyBlob)
716 {
717 struct tsp_object *obj;
718 struct tr_migdata_obj *migdata;
719 TPM_DIGEST pubKeyDigest;
720 TSS_RESULT result = TSS_SUCCESS;
721
722 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
723 return TSPERR(TSS_E_INVALID_HANDLE);
724
725 migdata = (struct tr_migdata_obj *)obj->data;
726
727 if ((result = obj_migdata_calc_pubkey_digest(blobSize, pubKeyBlob, &pubKeyDigest)))
728 goto done;
729
730 migdata->srcDigest = pubKeyDigest;
731
732 obj_migdata_calc_sig_data_digest(migdata);
733
734 done:
735 obj_list_put(&migdata_list);
736
737 return result;
738 }
739
740 TSS_RESULT
obj_migdata_set_src_digest(TSS_HMIGDATA hMigData,UINT32 digestSize,BYTE * digest)741 obj_migdata_set_src_digest(TSS_HMIGDATA hMigData, UINT32 digestSize, BYTE *digest)
742 {
743 struct tsp_object *obj;
744 struct tr_migdata_obj *migdata;
745 TSS_RESULT result = TSS_SUCCESS;
746
747 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
748 return TSPERR(TSS_E_INVALID_HANDLE);
749
750 migdata = (struct tr_migdata_obj *)obj->data;
751
752 if (digestSize != sizeof(migdata->srcDigest.digest)) {
753 result = TSPERR(TSS_E_BAD_PARAMETER);
754 goto done;
755 }
756 memcpy(migdata->srcDigest.digest, digest, sizeof(migdata->srcDigest.digest));
757
758 obj_migdata_calc_sig_data_digest(migdata);
759
760 done:
761 obj_list_put(&migdata_list);
762
763 return result;
764 }
765
766 TSS_RESULT
obj_migdata_get_src_digest(TSS_HMIGDATA hMigData,UINT32 * digestSize,BYTE ** digest)767 obj_migdata_get_src_digest(TSS_HMIGDATA hMigData, UINT32 *digestSize, BYTE **digest)
768 {
769 struct tsp_object *obj;
770 struct tr_migdata_obj *migdata;
771 TSS_RESULT result = TSS_SUCCESS;
772
773 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
774 return TSPERR(TSS_E_INVALID_HANDLE);
775
776 migdata = (struct tr_migdata_obj *)obj->data;
777
778 if ((*digest = calloc_tspi(obj->tspContext, sizeof(migdata->srcDigest.digest))) == NULL) {
779 LogError("malloc of %zd bytes failed.", sizeof(migdata->srcDigest.digest));
780 result = TSPERR(TSS_E_OUTOFMEMORY);
781 goto done;
782 }
783 memcpy(*digest, migdata->srcDigest.digest, sizeof(migdata->srcDigest.digest));
784 *digestSize = sizeof(migdata->srcDigest.digest);
785
786 done:
787 obj_list_put(&migdata_list);
788
789 return result;
790 }
791
792 TSS_RESULT
obj_migdata_set_cmk_auth(TSS_HMIGDATA hMigData,UINT32 digestsSize,BYTE * digests)793 obj_migdata_set_cmk_auth(TSS_HMIGDATA hMigData, UINT32 digestsSize, BYTE *digests)
794 {
795 struct tsp_object *obj;
796 struct tr_migdata_obj *migdata;
797 TSS_RESULT result = TSS_SUCCESS;
798
799 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
800 return TSPERR(TSS_E_INVALID_HANDLE);
801
802 migdata = (struct tr_migdata_obj *)obj->data;
803
804 if (digestsSize != (sizeof(migdata->maDigest.digest) +
805 sizeof(migdata->destDigest.digest) +
806 sizeof(migdata->srcDigest.digest))) {
807 result = TSPERR(TSS_E_BAD_PARAMETER);
808 goto done;
809 }
810 memcpy(migdata->maDigest.digest, digests, sizeof(migdata->maDigest.digest));
811 digests += sizeof(migdata->maDigest.digest);
812 memcpy(migdata->destDigest.digest, digests, sizeof(migdata->destDigest.digest));
813 digests += sizeof(migdata->destDigest.digest);
814 memcpy(migdata->srcDigest.digest, digests, sizeof(migdata->srcDigest.digest));
815
816 obj_migdata_calc_sig_data_digest(migdata);
817
818 done:
819 obj_list_put(&migdata_list);
820
821 return result;
822 }
823
824 TSS_RESULT
obj_migdata_get_cmk_auth(TSS_HMIGDATA hMigData,TPM_CMK_AUTH * cmkAuth)825 obj_migdata_get_cmk_auth(TSS_HMIGDATA hMigData, TPM_CMK_AUTH *cmkAuth)
826 {
827 struct tsp_object *obj;
828 struct tr_migdata_obj *migdata;
829
830 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
831 return TSPERR(TSS_E_INVALID_HANDLE);
832
833 migdata = (struct tr_migdata_obj *)obj->data;
834
835 cmkAuth->migrationAuthorityDigest = migdata->maDigest;
836 cmkAuth->destinationKeyDigest = migdata->destDigest;
837 cmkAuth->sourceKeyDigest = migdata->srcDigest;
838
839 obj_list_put(&migdata_list);
840
841 return TSS_SUCCESS;
842 }
843
844 TSS_RESULT
obj_migdata_get_cmk_auth_blob(TSS_HMIGDATA hMigData,UINT32 * blobSize,BYTE ** cmkAuthBlob)845 obj_migdata_get_cmk_auth_blob(TSS_HMIGDATA hMigData, UINT32 *blobSize, BYTE **cmkAuthBlob)
846 {
847 struct tsp_object *obj;
848 TPM_CMK_AUTH cmkAuth;
849 UINT64 offset;
850 TSS_RESULT result;
851
852 if ((result = obj_migdata_get_cmk_auth(hMigData, &cmkAuth)))
853 return result;
854
855 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
856 return TSPERR(TSS_E_INVALID_HANDLE);
857
858 offset = 0;
859 Trspi_LoadBlob_CMK_AUTH(&offset, NULL, &cmkAuth);
860
861 *blobSize = offset;
862 if ((*cmkAuthBlob = calloc_tspi(obj->tspContext, *blobSize)) == NULL) {
863 LogError("malloc of %u bytes failed.", *blobSize);
864 result = TSPERR(TSS_E_OUTOFMEMORY);
865 goto done;
866 }
867 offset = 0;
868 Trspi_LoadBlob_CMK_AUTH(&offset, *cmkAuthBlob, &cmkAuth);
869
870 done:
871 obj_list_put(&migdata_list);
872
873 return result;
874 }
875
876 TSS_RESULT
obj_migdata_set_sig_data(TSS_HMIGDATA hMigData,UINT32 sigDataSize,BYTE * sigData)877 obj_migdata_set_sig_data(TSS_HMIGDATA hMigData, UINT32 sigDataSize, BYTE *sigData)
878 {
879 struct tsp_object *obj;
880 struct tr_migdata_obj *migdata;
881 TSS_RESULT result = TSS_SUCCESS;
882
883 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
884 return TSPERR(TSS_E_INVALID_HANDLE);
885
886 migdata = (struct tr_migdata_obj *)obj->data;
887
888 if (sigDataSize != sizeof(migdata->sigData.digest)) {
889 result = TSPERR(TSS_E_BAD_PARAMETER);
890 goto done;
891 }
892 memcpy(migdata->sigData.digest, sigData, sizeof(migdata->sigData.digest));
893
894 done:
895 obj_list_put(&migdata_list);
896
897 return result;
898 }
899
900 TSS_RESULT
obj_migdata_get_sig_data(TSS_HMIGDATA hMigData,UINT32 * sigDataSize,BYTE ** sigData)901 obj_migdata_get_sig_data(TSS_HMIGDATA hMigData, UINT32 *sigDataSize, BYTE **sigData)
902 {
903 struct tsp_object *obj;
904 struct tr_migdata_obj *migdata;
905 TSS_RESULT result = TSS_SUCCESS;
906
907 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
908 return TSPERR(TSS_E_INVALID_HANDLE);
909
910 migdata = (struct tr_migdata_obj *)obj->data;
911
912 if ((*sigData = calloc_tspi(obj->tspContext, sizeof(migdata->sigData.digest))) == NULL) {
913 LogError("malloc of %zd bytes failed.", sizeof(migdata->sigData.digest));
914 result = TSPERR(TSS_E_OUTOFMEMORY);
915 goto done;
916 }
917 memcpy(*sigData, migdata->sigData.digest, sizeof(migdata->sigData.digest));
918 *sigDataSize = sizeof(migdata->sigData.digest);
919
920 done:
921 obj_list_put(&migdata_list);
922
923 return result;
924 }
925
926 TSS_RESULT
obj_migdata_set_sig_value(TSS_HMIGDATA hMigData,UINT32 sigValueSize,BYTE * sigValue)927 obj_migdata_set_sig_value(TSS_HMIGDATA hMigData, UINT32 sigValueSize, BYTE *sigValue)
928 {
929 struct tsp_object *obj;
930 struct tr_migdata_obj *migdata;
931 TSS_RESULT result = TSS_SUCCESS;
932
933 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
934 return TSPERR(TSS_E_INVALID_HANDLE);
935
936 migdata = (struct tr_migdata_obj *)obj->data;
937
938 migdata->sigValueSize = 0;
939 free(migdata->sigValue);
940 if ((migdata->sigValue = malloc(sigValueSize)) == NULL) {
941 LogError("malloc of %u bytes failed.", sigValueSize);
942 result = TSPERR(TSS_E_OUTOFMEMORY);
943 goto done;
944 }
945 memcpy(migdata->sigValue, sigValue, sigValueSize);
946 migdata->sigValueSize = sigValueSize;
947
948 done:
949 obj_list_put(&migdata_list);
950
951 return result;
952 }
953
954 TSS_RESULT
obj_migdata_get_sig_value(TSS_HMIGDATA hMigData,UINT32 * sigValueSize,BYTE ** sigValue)955 obj_migdata_get_sig_value(TSS_HMIGDATA hMigData, UINT32 *sigValueSize, BYTE **sigValue)
956 {
957 struct tsp_object *obj;
958 struct tr_migdata_obj *migdata;
959 TSS_RESULT result = TSS_SUCCESS;
960
961 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
962 return TSPERR(TSS_E_INVALID_HANDLE);
963
964 migdata = (struct tr_migdata_obj *)obj->data;
965
966 if ((*sigValue = calloc_tspi(obj->tspContext, migdata->sigValueSize)) == NULL) {
967 LogError("malloc of %u bytes failed.", migdata->sigValueSize);
968 result = TSPERR(TSS_E_OUTOFMEMORY);
969 goto done;
970 }
971 memcpy(*sigValue, migdata->sigValue, migdata->sigValueSize);
972 *sigValueSize = migdata->sigValueSize;
973
974 done:
975 obj_list_put(&migdata_list);
976
977 return result;
978 }
979
980 TSS_RESULT
obj_migdata_set_sig_ticket(TSS_HMIGDATA hMigData,UINT32 sigTicketSize,BYTE * sigTicket)981 obj_migdata_set_sig_ticket(TSS_HMIGDATA hMigData, UINT32 sigTicketSize, BYTE *sigTicket)
982 {
983 struct tsp_object *obj;
984 struct tr_migdata_obj *migdata;
985 TSS_RESULT result = TSS_SUCCESS;
986
987 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
988 return TSPERR(TSS_E_INVALID_HANDLE);
989
990 migdata = (struct tr_migdata_obj *)obj->data;
991
992 if (sigTicketSize != sizeof(migdata->sigTicket.digest)) {
993 result = TSPERR(TSS_E_BAD_PARAMETER);
994 goto done;
995 }
996 memcpy(migdata->sigTicket.digest, sigTicket, sizeof(migdata->sigTicket.digest));
997
998 done:
999 obj_list_put(&migdata_list);
1000
1001 return result;
1002 }
1003
1004 TSS_RESULT
obj_migdata_get_sig_ticket(TSS_HMIGDATA hMigData,UINT32 * sigTicketSize,BYTE ** sigTicket)1005 obj_migdata_get_sig_ticket(TSS_HMIGDATA hMigData, UINT32 *sigTicketSize, BYTE **sigTicket)
1006 {
1007 struct tsp_object *obj;
1008 struct tr_migdata_obj *migdata;
1009 TSS_RESULT result = TSS_SUCCESS;
1010
1011 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
1012 return TSPERR(TSS_E_INVALID_HANDLE);
1013
1014 migdata = (struct tr_migdata_obj *)obj->data;
1015
1016 if ((*sigTicket = calloc_tspi(obj->tspContext, sizeof(migdata->sigTicket.digest))) == NULL) {
1017 LogError("malloc of %zd bytes failed.", sizeof(migdata->sigTicket.digest));
1018 result = TSPERR(TSS_E_OUTOFMEMORY);
1019 goto done;
1020 }
1021 memcpy(*sigTicket, migdata->sigTicket.digest, sizeof(migdata->sigTicket.digest));
1022 *sigTicketSize = sizeof(migdata->sigTicket.digest);
1023
1024 done:
1025 obj_list_put(&migdata_list);
1026
1027 return result;
1028 }
1029
1030 TSS_RESULT
obj_migdata_set_blob(TSS_HMIGDATA hMigData,UINT32 blobSize,BYTE * blob)1031 obj_migdata_set_blob(TSS_HMIGDATA hMigData, UINT32 blobSize, BYTE *blob)
1032 {
1033 struct tsp_object *obj;
1034 struct tr_migdata_obj *migdata;
1035 TSS_RESULT result = TSS_SUCCESS;
1036
1037 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
1038 return TSPERR(TSS_E_INVALID_HANDLE);
1039
1040 migdata = (struct tr_migdata_obj *)obj->data;
1041
1042 migdata->blobSize = 0;
1043 free(migdata->blob);
1044 if ((migdata->blob = malloc(blobSize)) == NULL) {
1045 LogError("malloc of %u bytes failed.", blobSize);
1046 result = TSPERR(TSS_E_OUTOFMEMORY);
1047 goto done;
1048 }
1049 memcpy(migdata->blob, blob, blobSize);
1050 migdata->blobSize = blobSize;
1051
1052 done:
1053 obj_list_put(&migdata_list);
1054
1055 return result;
1056 }
1057
1058 TSS_RESULT
obj_migdata_get_blob(TSS_HMIGDATA hMigData,UINT32 * blobSize,BYTE ** blob)1059 obj_migdata_get_blob(TSS_HMIGDATA hMigData, UINT32 *blobSize, BYTE **blob)
1060 {
1061 struct tsp_object *obj;
1062 struct tr_migdata_obj *migdata;
1063 TSS_RESULT result = TSS_SUCCESS;
1064
1065 if ((obj = obj_list_get_obj(&migdata_list, hMigData)) == NULL)
1066 return TSPERR(TSS_E_INVALID_HANDLE);
1067
1068 migdata = (struct tr_migdata_obj *)obj->data;
1069
1070 if ((*blob = calloc_tspi(obj->tspContext, migdata->blobSize)) == NULL) {
1071 LogError("malloc of %u bytes failed.", migdata->blobSize);
1072 result = TSPERR(TSS_E_OUTOFMEMORY);
1073 goto done;
1074 }
1075 memcpy(*blob, migdata->blob, migdata->blobSize);
1076 *blobSize = migdata->blobSize;
1077
1078 done:
1079 obj_list_put(&migdata_list);
1080
1081 return result;
1082 }
1083
1084
1085 TSS_RESULT
obj_migdata_calc_pubkey_digest(UINT32 blobSize,BYTE * blob,TPM_DIGEST * digest)1086 obj_migdata_calc_pubkey_digest(UINT32 blobSize, BYTE *blob, TPM_DIGEST *digest)
1087 {
1088 Trspi_HashCtx hashCtx;
1089 TSS_RESULT result;
1090
1091 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1092 result |= Trspi_HashUpdate(&hashCtx, blobSize, blob);
1093 result |= Trspi_HashFinal(&hashCtx, digest->digest);
1094
1095 return result;
1096 }
1097
1098 TSS_RESULT
obj_migdata_calc_msa_digest(struct tr_migdata_obj * migdata)1099 obj_migdata_calc_msa_digest(struct tr_migdata_obj *migdata)
1100 {
1101 Trspi_HashCtx hashCtx;
1102 TSS_RESULT result;
1103
1104 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1105 result |= Trspi_Hash_MSA_COMPOSITE(&hashCtx, &migdata->msaList);
1106 result |= Trspi_HashFinal(&hashCtx, migdata->msaDigest.digest);
1107
1108 return result;
1109 }
1110
1111 TSS_RESULT
obj_migdata_calc_sig_data_digest(struct tr_migdata_obj * migdata)1112 obj_migdata_calc_sig_data_digest(struct tr_migdata_obj *migdata)
1113 {
1114 Trspi_HashCtx hashCtx;
1115 TSS_RESULT result;
1116
1117 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
1118 result |= Trspi_Hash_DIGEST(&hashCtx, migdata->maDigest.digest);
1119 result |= Trspi_Hash_DIGEST(&hashCtx, migdata->destDigest.digest);
1120 result |= Trspi_Hash_DIGEST(&hashCtx, migdata->srcDigest.digest);
1121 result |= Trspi_HashFinal(&hashCtx, migdata->sigData.digest);
1122
1123 return result;
1124 }
1125