Annotation of embedaddon/strongswan/src/libimcv/pts/pts.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2011-2012 Sansar Choinyambuu
3: * Copyright (C) 2012-2016 Andreas Steffen
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include "pts.h"
18:
19: #include <utils/debug.h>
20: #include <crypto/hashers/hasher.h>
21: #include <bio/bio_writer.h>
22: #include <bio/bio_reader.h>
23:
24: #include <tpm_tss.h>
25: #include <tpm_tss_trousers.h>
26:
27: #include <sys/types.h>
28: #include <sys/stat.h>
29: #include <libgen.h>
30: #include <unistd.h>
31: #include <errno.h>
32:
33: #ifndef TPM_TAG_QUOTE_INFO2
34: #define TPM_TAG_QUOTE_INFO2 0x0036
35: #endif
36: #ifndef TPM_LOC_ZERO
37: #define TPM_LOC_ZERO 0x01
38: #endif
39:
40: typedef struct private_pts_t private_pts_t;
41:
42: /**
43: * Private data of a pts_t object.
44: *
45: */
46: struct private_pts_t {
47:
48: /**
49: * Public pts_t interface.
50: */
51: pts_t public;
52:
53: /**
54: * PTS Protocol Capabilities
55: */
56: pts_proto_caps_flag_t proto_caps;
57:
58: /**
59: * PTS Measurement Algorithm
60: */
61: pts_meas_algorithms_t algorithm;
62:
63: /**
64: * DH Hash Algorithm
65: */
66: pts_meas_algorithms_t dh_hash_algorithm;
67:
68: /**
69: * PTS Diffie-Hellman Secret
70: */
71: diffie_hellman_t *dh;
72:
73: /**
74: * PTS Diffie-Hellman Initiator Nonce
75: */
76: chunk_t initiator_nonce;
77:
78: /**
79: * PTS Diffie-Hellman Responder Nonce
80: */
81: chunk_t responder_nonce;
82:
83: /**
84: * Secret assessment value to be used for TPM Quote as an external data
85: */
86: chunk_t secret;
87:
88: /**
89: * Primary key of platform entry in database
90: */
91: int platform_id;
92:
93: /**
94: * TRUE if IMC-PTS, FALSE if IMV-PTS
95: */
96: bool is_imc;
97:
98: /**
99: * Active TPM
100: */
101: tpm_tss_t *tpm;
102:
103: /**
104: * Contains a TPM_CAP_VERSION_INFO struct
105: */
106: chunk_t tpm_version_info;
107:
108: /**
109: * AIK object handle
110: */
111: uint32_t aik_handle;
112:
113: /**
114: * Contains an Attestation Identity Key Certificate
115: */
116: certificate_t *aik_cert;
117:
118: /**
119: * Primary key referencing AIK in database
120: */
121: int aik_id;
122:
123: /**
124: * Shadow PCR set
125: */
126: pts_pcr_t *pcrs;
127:
128: };
129:
130: METHOD(pts_t, get_proto_caps, pts_proto_caps_flag_t,
131: private_pts_t *this)
132: {
133: return this->proto_caps;
134: }
135:
136: METHOD(pts_t, set_proto_caps, void,
137: private_pts_t *this, pts_proto_caps_flag_t flags)
138: {
139: this->proto_caps = flags;
140: DBG2(DBG_PTS, "supported PTS protocol capabilities: %s%s%s%s%s",
141: flags & PTS_PROTO_CAPS_C ? "C" : ".",
142: flags & PTS_PROTO_CAPS_V ? "V" : ".",
143: flags & PTS_PROTO_CAPS_D ? "D" : ".",
144: flags & PTS_PROTO_CAPS_T ? "T" : ".",
145: flags & PTS_PROTO_CAPS_X ? "X" : ".");
146: }
147:
148: METHOD(pts_t, get_meas_algorithm, pts_meas_algorithms_t,
149: private_pts_t *this)
150: {
151: return this->algorithm;
152: }
153:
154: METHOD(pts_t, set_meas_algorithm, void,
155: private_pts_t *this, pts_meas_algorithms_t algorithm)
156: {
157: hash_algorithm_t hash_alg;
158:
159: hash_alg = pts_meas_algo_to_hash(algorithm);
160: DBG2(DBG_PTS, "selected PTS measurement algorithm is %N",
161: hash_algorithm_names, hash_alg);
162: if (hash_alg != HASH_UNKNOWN)
163: {
164: this->algorithm = algorithm;
165: }
166: }
167:
168: METHOD(pts_t, get_dh_hash_algorithm, pts_meas_algorithms_t,
169: private_pts_t *this)
170: {
171: return this->dh_hash_algorithm;
172: }
173:
174: METHOD(pts_t, set_dh_hash_algorithm, void,
175: private_pts_t *this, pts_meas_algorithms_t algorithm)
176: {
177: hash_algorithm_t hash_alg;
178:
179: hash_alg = pts_meas_algo_to_hash(algorithm);
180: DBG2(DBG_PTS, "selected DH hash algorithm is %N",
181: hash_algorithm_names, hash_alg);
182: if (hash_alg != HASH_UNKNOWN)
183: {
184: this->dh_hash_algorithm = algorithm;
185: }
186: }
187:
188: METHOD(pts_t, create_dh_nonce, bool,
189: private_pts_t *this, pts_dh_group_t group, int nonce_len)
190: {
191: diffie_hellman_group_t dh_group;
192: chunk_t *nonce;
193: rng_t *rng;
194:
195: dh_group = pts_dh_group_to_ike(group);
196: DBG2(DBG_PTS, "selected PTS DH group is %N",
197: diffie_hellman_group_names, dh_group);
198: DESTROY_IF(this->dh);
199: this->dh = lib->crypto->create_dh(lib->crypto, dh_group);
200:
201: rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
202: if (!rng)
203: {
204: DBG1(DBG_PTS, "no rng available");
205: return FALSE;
206: }
207: DBG2(DBG_PTS, "nonce length is %d", nonce_len);
208: nonce = this->is_imc ? &this->responder_nonce : &this->initiator_nonce;
209: chunk_free(nonce);
210: if (!rng->allocate_bytes(rng, nonce_len, nonce))
211: {
212: DBG1(DBG_PTS, "failed to allocate nonce");
213: rng->destroy(rng);
214: return FALSE;
215: }
216: rng->destroy(rng);
217: return TRUE;
218: }
219:
220: METHOD(pts_t, get_my_public_value, bool,
221: private_pts_t *this, chunk_t *value, chunk_t *nonce)
222: {
223: if (!this->dh->get_my_public_value(this->dh, value))
224: {
225: return FALSE;
226: }
227: *nonce = this->is_imc ? this->responder_nonce : this->initiator_nonce;
228: return TRUE;
229: }
230:
231: METHOD(pts_t, set_peer_public_value, bool,
232: private_pts_t *this, chunk_t value, chunk_t nonce)
233: {
234: if (!this->dh->set_other_public_value(this->dh, value))
235: {
236: return FALSE;
237: }
238:
239: nonce = chunk_clone(nonce);
240: if (this->is_imc)
241: {
242: this->initiator_nonce = nonce;
243: }
244: else
245: {
246: this->responder_nonce = nonce;
247: }
248: return TRUE;
249: }
250:
251: METHOD(pts_t, calculate_secret, bool,
252: private_pts_t *this)
253: {
254: hasher_t *hasher;
255: hash_algorithm_t hash_alg;
256: chunk_t shared_secret;
257:
258: /* Check presence of nonces */
259: if (!this->initiator_nonce.len || !this->responder_nonce.len)
260: {
261: DBG1(DBG_PTS, "initiator and/or responder nonce is not available");
262: return FALSE;
263: }
264: DBG3(DBG_PTS, "initiator nonce: %B", &this->initiator_nonce);
265: DBG3(DBG_PTS, "responder nonce: %B", &this->responder_nonce);
266:
267: /* Calculate the DH secret */
268: if (!this->dh->get_shared_secret(this->dh, &shared_secret))
269: {
270: DBG1(DBG_PTS, "shared DH secret computation failed");
271: return FALSE;
272: }
273: DBG3(DBG_PTS, "shared DH secret: %B", &shared_secret);
274:
275: /* Calculate the secret assessment value */
276: hash_alg = pts_meas_algo_to_hash(this->dh_hash_algorithm);
277: hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
278:
279: if (!hasher ||
280: !hasher->get_hash(hasher, chunk_from_chars('1'), NULL) ||
281: !hasher->get_hash(hasher, this->initiator_nonce, NULL) ||
282: !hasher->get_hash(hasher, this->responder_nonce, NULL) ||
283: !hasher->allocate_hash(hasher, shared_secret, &this->secret))
284: {
285: DESTROY_IF(hasher);
286: return FALSE;
287: }
288: hasher->destroy(hasher);
289:
290: /* The DH secret must be destroyed */
291: chunk_clear(&shared_secret);
292:
293: /*
294: * Truncate the hash to 20 bytes to fit the ExternalData
295: * argument of the TPM Quote command
296: */
297: this->secret.len = min(this->secret.len, 20);
298: DBG3(DBG_PTS, "secret assessment value: %B", &this->secret);
299: return TRUE;
300: }
301:
302: METHOD(pts_t, get_platform_id, int,
303: private_pts_t *this)
304: {
305: return this->platform_id;
306: }
307:
308: METHOD(pts_t, set_platform_id, void,
309: private_pts_t *this, int pid)
310: {
311: this->platform_id = pid;
312: }
313:
314: METHOD(pts_t, get_tpm_version_info, bool,
315: private_pts_t *this, chunk_t *info)
316: {
317: *info = this->tpm ? this->tpm->get_version_info(this->tpm) :
318: this->tpm_version_info;
319: return info->len > 0;
320: }
321:
322: METHOD(pts_t, set_tpm_version_info, void,
323: private_pts_t *this, chunk_t info)
324: {
325: this->tpm_version_info = chunk_clone(info);
326: }
327:
328: /**
329: * Load an AIK handle and an optional AIK certificate and
330: * in the case of a TPM 1.2 an AIK private key blob plus matching public key,
331: * the certificate having precedence over the public key if both are present
332: */
333: static void load_aik(private_pts_t *this)
334: {
335: char *handle_str, *cert_path, *key_path, *blob_path;
336: chunk_t aik_pubkey = chunk_empty;
337:
338: handle_str = lib->settings->get_str(lib->settings,
339: "%s.plugins.imc-attestation.aik_handle", NULL, lib->ns);
340: cert_path = lib->settings->get_str(lib->settings,
341: "%s.plugins.imc-attestation.aik_cert", NULL, lib->ns);
342: key_path = lib->settings->get_str(lib->settings,
343: "%s.plugins.imc-attestation.aik_pubkey", NULL, lib->ns);
344: blob_path = lib->settings->get_str(lib->settings,
345: "%s.plugins.imc-attestation.aik_blob", NULL, lib->ns);
346:
347: if (handle_str)
348: {
349: this->aik_handle = strtoll(handle_str, NULL, 16);
350: }
351: if (cert_path)
352: {
353: this->aik_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
354: CERT_X509, BUILD_FROM_FILE,
355: cert_path, BUILD_END);
356: if (this->aik_cert)
357: {
358: DBG2(DBG_PTS, "loaded AIK certificate from '%s'", cert_path);
359: }
360: }
361:
362: if (this->tpm->get_version(this->tpm) == TPM_VERSION_1_2)
363: {
364: tpm_tss_trousers_t *tpm_12;
365: chunk_t aik_blob = chunk_empty;
366: chunk_t *map;
367:
368: /* get AIK private key blob */
369: if (blob_path)
370: {
371: map = chunk_map(blob_path, FALSE);
372: if (map)
373: {
374: DBG2(DBG_PTS, "loaded AIK Blob from '%s'", blob_path);
375: DBG3(DBG_PTS, "AIK Blob: %B", map);
376: aik_blob = chunk_clone(*map);
377: chunk_unmap(map);
378: }
379: else
380: {
381: DBG1(DBG_PTS, "unable to map AIK Blob file '%s': %s",
382: blob_path, strerror(errno));
383: }
384: }
385: else
386: {
387: DBG1(DBG_PTS, "AIK Blob is not available");
388: }
389:
390: /* get AIK public key if no AIK certificate is available */
391: if (!this->aik_cert)
392: {
393: if (key_path)
394: {
395: map = chunk_map(key_path, FALSE);
396: if (map)
397: {
398: DBG2(DBG_PTS, "loaded AIK public key from '%s'", key_path);
399: aik_pubkey = chunk_clone(*map);
400: chunk_unmap(map);
401: }
402: else
403: {
404: DBG1(DBG_PTS, "unable to map AIK public key file '%s': %s",
405: key_path, strerror(errno));
406: }
407: }
408: else
409: {
410: DBG1(DBG_PTS, "AIK public key is not available");
411: }
412: }
413:
414: /* Load AIK item into TPM 1.2 object */
415: tpm_12 = (tpm_tss_trousers_t *)this->tpm;
416: tpm_12->load_aik(tpm_12, aik_blob, aik_pubkey, this->aik_handle);
417: }
418:
419: /* if no signed X.509 AIK certificate is available use public key instead */
420: if (!this->aik_cert)
421: {
422: aik_pubkey = this->tpm->get_public(this->tpm, this->aik_handle);
423: if (aik_pubkey.len > 0)
424: {
425: this->aik_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
426: CERT_TRUSTED_PUBKEY, BUILD_BLOB,
427: aik_pubkey, BUILD_END);
428: chunk_free(&aik_pubkey);
429: }
430: else
431: {
432: DBG1(DBG_PTS, "neither AIK certificate nor public key is available");
433: }
434: }
435: }
436:
437: METHOD(pts_t, get_aik, certificate_t*,
438: private_pts_t *this)
439: {
440: return this->aik_cert;
441: }
442:
443: METHOD(pts_t, set_aik, void,
444: private_pts_t *this, certificate_t *aik, int aik_id)
445: {
446: DESTROY_IF(this->aik_cert);
447: this->aik_cert = aik->get_ref(aik);
448: this->aik_id = aik_id;
449: }
450:
451: METHOD(pts_t, get_aik_id, int,
452: private_pts_t *this)
453: {
454: return this->aik_id;
455: }
456:
457: METHOD(pts_t, is_path_valid, bool,
458: private_pts_t *this, char *path, pts_error_code_t *error_code)
459: {
460: struct stat st;
461:
462: *error_code = 0;
463:
464: if (!stat(path, &st))
465: {
466: return TRUE;
467: }
468: else if (errno == ENOENT || errno == ENOTDIR)
469: {
470: DBG1(DBG_PTS, "file/directory does not exist %s", path);
471: *error_code = TCG_PTS_FILE_NOT_FOUND;
472: }
473: else if (errno == EFAULT)
474: {
475: DBG1(DBG_PTS, "bad address %s", path);
476: *error_code = TCG_PTS_INVALID_PATH;
477: }
478: else
479: {
480: DBG1(DBG_PTS, "error: %s occurred while validating path: %s",
481: strerror(errno), path);
482: return FALSE;
483: }
484:
485: return TRUE;
486: }
487:
488: /**
489: * Obtain statistical information describing a file
490: */
491: static bool file_metadata(char *pathname, pts_file_metadata_t **entry)
492: {
493: struct stat st;
494: pts_file_metadata_t *this;
495:
496: this = malloc_thing(pts_file_metadata_t);
497:
498: if (stat(pathname, &st))
499: {
500: DBG1(DBG_PTS, "unable to obtain statistics about '%s'", pathname);
501: free(this);
502: return FALSE;
503: }
504:
505: if (S_ISREG(st.st_mode))
506: {
507: this->type = PTS_FILE_REGULAR;
508: }
509: else if (S_ISDIR(st.st_mode))
510: {
511: this->type = PTS_FILE_DIRECTORY;
512: }
513: else if (S_ISCHR(st.st_mode))
514: {
515: this->type = PTS_FILE_CHAR_SPEC;
516: }
517: else if (S_ISBLK(st.st_mode))
518: {
519: this->type = PTS_FILE_BLOCK_SPEC;
520: }
521: else if (S_ISFIFO(st.st_mode))
522: {
523: this->type = PTS_FILE_FIFO;
524: }
525: #ifndef WIN32
526: else if (S_ISLNK(st.st_mode))
527: {
528: this->type = PTS_FILE_SYM_LINK;
529: }
530: else if (S_ISSOCK(st.st_mode))
531: {
532: this->type = PTS_FILE_SOCKET;
533: }
534: #endif /* WIN32 */
535: else
536: {
537: this->type = PTS_FILE_OTHER;
538: }
539:
540: this->filesize = st.st_size;
541: this->created = st.st_ctime;
542: this->modified = st.st_mtime;
543: this->accessed = st.st_atime;
544: this->owner = st.st_uid;
545: this->group = st.st_gid;
546:
547: *entry = this;
548: return TRUE;
549: }
550:
551: METHOD(pts_t, get_metadata, pts_file_meta_t*,
552: private_pts_t *this, char *pathname, bool is_directory)
553: {
554: pts_file_meta_t *metadata;
555: pts_file_metadata_t *entry;
556:
557: /* Create a metadata object */
558: metadata = pts_file_meta_create();
559:
560: if (is_directory)
561: {
562: enumerator_t *enumerator;
563: char *rel_name, *abs_name;
564: struct stat st;
565:
566: enumerator = enumerator_create_directory(pathname);
567: if (!enumerator)
568: {
569: DBG1(DBG_PTS," directory '%s' can not be opened, %s", pathname,
570: strerror(errno));
571: metadata->destroy(metadata);
572: return NULL;
573: }
574: while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
575: {
576: /* measure regular files only */
577: if (S_ISREG(st.st_mode) && *rel_name != '.')
578: {
579: if (!file_metadata(abs_name, &entry))
580: {
581: enumerator->destroy(enumerator);
582: metadata->destroy(metadata);
583: return NULL;
584: }
585: entry->filename = strdup(rel_name);
586: metadata->add(metadata, entry);
587: }
588: }
589: enumerator->destroy(enumerator);
590: }
591: else
592: {
593: if (!file_metadata(pathname, &entry))
594: {
595: metadata->destroy(metadata);
596: return NULL;
597: }
598: entry->filename = path_basename(pathname);
599: metadata->add(metadata, entry);
600: }
601:
602: return metadata;
603: }
604:
605: METHOD(pts_t, read_pcr, bool,
606: private_pts_t *this, uint32_t pcr_num, chunk_t *pcr_value,
607: hash_algorithm_t alg)
608: {
609: return this->tpm ? this->tpm->read_pcr(this->tpm, pcr_num, pcr_value, alg)
610: : FALSE;
611: }
612:
613: METHOD(pts_t, extend_pcr, bool,
614: private_pts_t *this, uint32_t pcr_num, chunk_t *pcr_value, chunk_t data,
615: hash_algorithm_t alg)
616: {
617: if (!this->tpm->extend_pcr(this->tpm, pcr_num, pcr_value, data, alg))
618: {
619: return FALSE;
620: }
621: DBG3(DBG_PTS, "PCR %d extended with: %#B", pcr_num, &data);
622: DBG3(DBG_PTS, "PCR %d after extension: %#B", pcr_num, pcr_value);
623:
624: return TRUE;
625: }
626:
627: METHOD(pts_t, quote, bool,
628: private_pts_t *this, tpm_quote_mode_t *quote_mode,
629: tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
630: {
631: chunk_t pcr_value, pcr_computed;
632: uint32_t pcr, pcr_sel = 0;
633: enumerator_t *enumerator;
634:
635: /* select PCRs */
636: DBG2(DBG_PTS, "PCR values hashed into PCR Composite:");
637: enumerator = this->pcrs->create_enumerator(this->pcrs);
638: while (enumerator->enumerate(enumerator, &pcr))
639: {
640: if (this->tpm->read_pcr(this->tpm, pcr, &pcr_value, HASH_SHA1))
641: {
642: pcr_computed = this->pcrs->get(this->pcrs, pcr);
643: DBG2(DBG_PTS, "PCR %2d %#B %s", pcr, &pcr_value,
644: chunk_equals(pcr_value, pcr_computed) ? "ok" : "differs");
645: chunk_free(&pcr_value);
646: };
647:
648: /* add PCR to selection list */
649: pcr_sel |= (1 << pcr);
650: }
651: enumerator->destroy(enumerator);
652:
653: /* TPM Quote */
654: return this->tpm->quote(this->tpm, this->aik_handle, pcr_sel, HASH_SHA1,
655: this->secret, quote_mode, quote_info, quote_sig);
656: }
657:
658: METHOD(pts_t, get_quote, bool,
659: private_pts_t *this, tpm_tss_quote_info_t *quote_info, chunk_t *quoted)
660: {
661: tpm_tss_pcr_composite_t *pcr_composite;
662: bool success;
663:
664: if (!this->pcrs->get_count(this->pcrs))
665: {
666: DBG1(DBG_PTS, "No extended PCR entries available, "
667: "unable to construct TPM Quote Info");
668: return FALSE;
669: }
670: if (!this->secret.ptr)
671: {
672: DBG1(DBG_PTS, "Secret assessment value unavailable, ",
673: "unable to construct TPM Quote Info");
674: return FALSE;
675: }
676: if (quote_info->get_quote_mode(quote_info) == TPM_QUOTE2_VERSION_INFO)
677: {
678: if (!this->tpm_version_info.ptr)
679: {
680: DBG1(DBG_PTS, "TPM Version Information unavailable, ",
681: "unable to construct TPM Quote Info2");
682: return FALSE;
683: }
684: quote_info->set_version_info(quote_info, this->tpm_version_info);
685: }
686: pcr_composite = this->pcrs->get_composite(this->pcrs);
687:
688: success = quote_info->get_quote(quote_info, this->secret,
689: pcr_composite, quoted);
690: chunk_free(&pcr_composite->pcr_select);
691: chunk_free(&pcr_composite->pcr_composite);
692: free(pcr_composite);
693:
694: return success;
695: }
696:
697: METHOD(pts_t, verify_quote_signature, bool,
698: private_pts_t *this, hash_algorithm_t digest_alg, chunk_t digest,
699: chunk_t signature)
700: {
701: public_key_t *aik_pubkey;
702: signature_scheme_t scheme;
703:
704: aik_pubkey = this->aik_cert->get_public_key(this->aik_cert);
705: if (!aik_pubkey)
706: {
707: DBG1(DBG_PTS, "failed to get public key from AIK certificate");
708: return FALSE;
709: }
710:
711: /* Determine signing scheme */
712: switch (aik_pubkey->get_type(aik_pubkey))
713: {
714: case KEY_RSA:
715: switch (digest_alg)
716: {
717: case HASH_SHA1:
718: scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
719: break;
720: case HASH_SHA256:
721: scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256;
722: break;
723: case HASH_SHA384:
724: scheme = SIGN_RSA_EMSA_PKCS1_SHA2_384;
725: break;
726: case HASH_SHA512:
727: scheme = SIGN_RSA_EMSA_PKCS1_SHA2_512;
728: break;
729: case HASH_SHA3_256:
730: scheme = SIGN_RSA_EMSA_PKCS1_SHA3_256;
731: break;
732: case HASH_SHA3_384:
733: scheme = SIGN_RSA_EMSA_PKCS1_SHA3_384;
734: break;
735: case HASH_SHA3_512:
736: scheme = SIGN_RSA_EMSA_PKCS1_SHA3_512;
737: break;
738: default:
739: scheme = SIGN_UNKNOWN;
740: }
741: break;
742: case KEY_ECDSA:
743: switch (digest_alg)
744: {
745: case HASH_SHA256:
746: scheme = SIGN_ECDSA_256;
747: break;
748: case HASH_SHA384:
749: scheme = SIGN_ECDSA_384;
750: break;
751: case HASH_SHA512:
752: scheme = SIGN_ECDSA_521;
753: break;
754: default:
755: scheme = SIGN_UNKNOWN;
756: }
757: break;
758: default:
759: DBG1(DBG_PTS, "%N AIK key type not supported", key_type_names,
760: aik_pubkey->get_type(aik_pubkey));
761: return FALSE;
762: }
763:
764: if (!aik_pubkey->verify(aik_pubkey, scheme, NULL, digest, signature))
765: {
766: DBG1(DBG_PTS, "signature verification failed for TPM Quote Info");
767: DESTROY_IF(aik_pubkey);
768: return FALSE;
769: }
770:
771: aik_pubkey->destroy(aik_pubkey);
772: return TRUE;
773: }
774:
775: METHOD(pts_t, get_pcrs, pts_pcr_t*,
776: private_pts_t *this)
777: {
778: return this->pcrs;
779: }
780:
781: METHOD(pts_t, destroy, void,
782: private_pts_t *this)
783: {
784: DESTROY_IF(this->tpm);
785: DESTROY_IF(this->pcrs);
786: DESTROY_IF(this->aik_cert);
787: DESTROY_IF(this->dh);
788: free(this->initiator_nonce.ptr);
789: free(this->responder_nonce.ptr);
790: free(this->secret.ptr);
791: free(this->tpm_version_info.ptr);
792: free(this);
793: }
794:
795: /**
796: * See header
797: */
798: pts_t *pts_create(bool is_imc)
799: {
800: private_pts_t *this;
801: pts_pcr_t *pcrs;
802:
803: pcrs = pts_pcr_create();
804: if (!pcrs)
805: {
806: DBG1(DBG_PTS, "shadow PCR set could not be created");
807: return NULL;
808: }
809:
810: INIT(this,
811: .public = {
812: .get_proto_caps = _get_proto_caps,
813: .set_proto_caps = _set_proto_caps,
814: .get_meas_algorithm = _get_meas_algorithm,
815: .set_meas_algorithm = _set_meas_algorithm,
816: .get_dh_hash_algorithm = _get_dh_hash_algorithm,
817: .set_dh_hash_algorithm = _set_dh_hash_algorithm,
818: .create_dh_nonce = _create_dh_nonce,
819: .get_my_public_value = _get_my_public_value,
820: .set_peer_public_value = _set_peer_public_value,
821: .calculate_secret = _calculate_secret,
822: .get_platform_id = _get_platform_id,
823: .set_platform_id = _set_platform_id,
824: .get_tpm_version_info = _get_tpm_version_info,
825: .set_tpm_version_info = _set_tpm_version_info,
826: .get_aik = _get_aik,
827: .set_aik = _set_aik,
828: .get_aik_id = _get_aik_id,
829: .is_path_valid = _is_path_valid,
830: .get_metadata = _get_metadata,
831: .read_pcr = _read_pcr,
832: .extend_pcr = _extend_pcr,
833: .quote = _quote,
834: .get_pcrs = _get_pcrs,
835: .get_quote = _get_quote,
836: .verify_quote_signature = _verify_quote_signature,
837: .destroy = _destroy,
838: },
839: .is_imc = is_imc,
840: .proto_caps = PTS_PROTO_CAPS_V,
841: .algorithm = PTS_MEAS_ALGO_SHA256,
842: .dh_hash_algorithm = PTS_MEAS_ALGO_SHA256,
843: .pcrs = pcrs,
844: );
845:
846: if (is_imc)
847: {
848: this->tpm = tpm_tss_probe(TPM_VERSION_ANY);
849: if (this->tpm)
850: {
851: this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
852: load_aik(this);
853: }
854: }
855: else
856: {
857: this->proto_caps |= PTS_PROTO_CAPS_T | PTS_PROTO_CAPS_D;
858: }
859:
860: return &this->public;
861: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>