From: Jonathan M. <jon...@cm...> - 2011-09-08 19:45:05
|
Hi list, I'm having a tough time recomputing the values that I find in PCR 17 following SENTER. I'm using i5_i7_DUAL_SINIT_18.BIN (I believe this to be the latest available), which produces a version 7 sinit_to_mle_data. Looking at Section 1.9.1 in the spec, it's quite unclear to me exactly what it's trying to tell me will be in PCR 17. >From the spec: If SinitMleData.Version = 7, PCR 17’s final value will be: SHA-1 ( SinitMleData.SinitHash | SHA-1 ( SinitMleData.BiosAcm.ID | SinitMleData.MsegValid | SinitMleData.StmHash | SinitMleData.PolicyControl | SinitMleData.LcpPolicyHash | (OsSinitData.Capabilities, 0) ) ) There are at least three problems with this. (1) There is no mention of a PCR Extend (contrast with the clear explanation for version 6 sinit_to_mle_data which I have used successfully in the past), and (2) This expression is inconsistent with the paragraph at the start of Section 1.9.1 which mentions the use of SHA-256 to hash the "SINIT ACM". I don't see SHA-256 in that expression anywhere. (3) It is not mentioned whether the 4-byte EdxSenterFlags is also input to SHA-256 or not. I'd rather not try to map out all the different possibilities and figure this out experimentally. Things don't look much better for version 8 but I don't have the hardware to test that. Thanks! -Jon |
From: JP B. <jp...@co...> - 2011-09-08 20:35:20
|
Jonathan McCune <jonmccune <at> cmu.edu> writes: > > Hi list, > > I'm having a tough time recomputing the values that I find in PCR 17 > following SENTER. I'm using i5_i7_DUAL_SINIT_18.BIN (I believe this > to be the latest available), which produces a version 7 > sinit_to_mle_data. > > Looking at Section 1.9.1 in the spec, it's quite unclear to me exactly > what it's trying to tell me will be in PCR 17. > > >From the spec: > > If SinitMleData.Version = 7, PCR 17’s final value will be: > > SHA-1 ( SinitMleData.SinitHash | SHA-1 ( SinitMleData.BiosAcm.ID | > SinitMleData.MsegValid | SinitMleData.StmHash | SinitMleData.PolicyControl | > SinitMleData.LcpPolicyHash | (OsSinitData.Capabilities, 0) ) ) > > There are at least three problems with this. (1) There is no mention > of a PCR Extend (contrast with the clear explanation for version 6 > sinit_to_mle_data which I have used successfully in the past), and (2) > This expression is inconsistent with the paragraph at the start of > Section 1.9.1 which mentions the use of SHA-256 to hash the "SINIT > ACM". I don't see SHA-256 in that expression anywhere. (3) It is not > mentioned whether the 4-byte EdxSenterFlags is also input to SHA-256 > or not. > > I'd rather not try to map out all the different possibilities and > figure this out experimentally. > > Things don't look much better for version 8 but I don't have the > hardware to test that. > > Thanks! > -Jon > > ------------------------------------------------------------------------------ > Doing More with Less: The Next Generation Virtual Desktop > What are the key obstacles that have prevented many mid-market businesses > from deploying virtual desktops? How do next-generation virtual desktops > provide companies an easier-to-deploy, easier-to-manage and more affordable > virtual desktop model.http://www.accelacomm.com/jaw/sfnl/114/51426474/ > These are the steps I took to repro PCR-17. Hope it helps. ############################################################################### #PCR17 Calculation (SinitMleData_Version=7) ############################################################################### SinitMleData_SinitHash=$( txt-stat | grep sinit_hash -A1 | tail -n1 | awk '{gsub(/ /,"");print $1}') SinitMleData_BiosAcmID==$( txt-stat | grep bios_acm_id -A1 | tail -n1 | awk '{gsub(/ /,"");print $1}') SinitMleData_MsegValid="0000000000000000" SinitMleData_StmHash="0000000000000000000000000000000000000000" SinitMleData_PolicyControl="00000000" # will be non-zero if an LCP is defined SinitMleData_LcpPolicyHash=$( txt-stat | grep lcp_policy_hash -A1 | tail -n1 | awk '{gsub(/ /,"");print $1}') OsSinitData_Capabilities="00000000" #as defined in Sec 1.9.1 (pp.14) of "Intel TXT Software Dev Guide, MLE Dev Guide, March 2011" PCR17_PARTB1="$SinitMleData_BiosAcmID$SinitMleData_MsegValid$SinitMleData_StmHa sh$SinitMleData_PolicyControl$SinitMleData_LcpPolicyHash$OsSinitData_Capabiliti es" PCR17_STEP1=$(echo -n "$PCR17_PARTB1" | ./binaryfi | sha1sum | awk '{ print $1 }') echo "value extending PCR17 (i.e. sinit_hash) = $(fmt_bytestr $PCR17_STEP1)" PCR17_PRE_VL=$(echo -n "$SinitMleData_SinitHash$PCR17_STEP1" | ./binaryfi | sha1sum | awk '{ print $1 }' ) POLICY_HASH=$( txt-stat | grep " pol_hash:" | awk -F 'pol_hash:' '{ gsub(/ /,""); print $2}') # Using policy_control from `txt-stat | grep " policy_control:" | head -n 1` # Remember endianess! POLICY_CONTROL="01000000" PCR17_VL_MEAS=$(echo -n "$POLICY_CONTROL$POLICY_HASH" | ./binaryfi | sha1sum | awk '{ print $1 }') echo "PENULTIMATE_PCR17= $(fmt_bytestr $PCR17_PRE_VL)" echo "PCR17_VL_MEAS= $(fmt_bytestr $PCR17_VL_MEAS)" # -o is old value, -n is new value PCR17_FINAL=$(./mimic_extend.sh -o "$PCR17_PRE_VL" -n "$PCR17_VL_MEAS") -JP |
From: Jonathan M. <jon...@cm...> - 2011-09-09 15:55:46
|
Hello again, Some progress to report! I've decided to write in with an incomplete investigation because I suspect lots of other folks have similar questions / concerns. First, thank you JP for sharing your method. Upon reading the spec more carefully, I realize that the nested SHA-1 expression for the contents of PCR-17 is indeed correct: SHA-1 ( SinitMleData.SinitHash | SHA-1 ( SinitMleData.BiosAcm.ID | SinitMleData.MsegValid | SinitMleData.StmHash | SinitMleData.PolicyControl | SinitMleData.LcpPolicyHash | (OsSinitData.Capabilities, 0) ) ) What was not initially clear to me is that SinitMleData.SinitHash is not actually the hash of the SINIT for a Version 7 SinitMleData. It is the PCR-17 value following the "first extend". As with a version 6 SinitMleData, there are two extends to PCR-17. The nested SHA-1 expression in the spec is actually a verbose version of the "second extend". To me, the following is more clear: /* first extend (XXX have not confirmed that these inputs are correct XXX) */ Extend-PCR17 ( sha-256 hash ( SINIT ACM | EdxSenterFlags ) ) /* not an input to either extend, rather an intermediate value to aid in PCR reconstruction post-launch */ Read PCR17 into SinitMleData.SinitHash /* second extend (have successfully confirmed that this is indeed correct) */ Extend-PCR17(SHA-1 ( SinitMleData.BiosAcm.ID | SinitMleData.MsegValid | SinitMleData.StmHash | SinitMleData.PolicyControl | SinitMleData.LcpPolicyHash | (OsSinitData.Capabilities, 0) ) Once more: The "second extend" is equivalent to the SHA-1 expression listed in the spec. Now, I have successfully recomputed the "second extend" taking on faith that SinitMleData.SinitHash does in fact represent the result of the "first extend" shown above. However, I don't want to take it on faith. I want to recompute it. What follows is my current read of the spec, which is so far INCORRECT. However, I still want to detail my thinking here, in case anybody is able to point out where it goes wrong: The "first extend" listed above: Extend-PCR17 ( sha-256 hash(SINIT ACM | EdxSenterFlags ) ) ...breaks apart into: SHA-1(0x00^20 | SHA-1 ( SHA-256 ( SINIT ACM | EdxSenterFlags ) ) ) ... and that result should be equivalent to the value that I find in SinitMleData.SinitHash. Right now the thing that I believe is most likely to be incorrect is the value that I am using for "SINIT ACM" in the input to sha-256. I am simply using the entire contents of the file i5_i7_DUAL_SINIT_18.BIN. I suspect I need to parse that file and strip off some metadata. I will write in again when if / when I get this figured out. In the mean time, thanks for any hints that anybody can provide! Regards, -Jon |
From: Cihula, J. <jos...@in...> - 2011-09-09 22:58:43
|
> From: Jonathan McCune [mailto:jon...@cm...] > Sent: Friday, September 09, 2011 8:56 AM > > Hello again, > > Some progress to report! I've decided to write in with an incomplete investigation because I > suspect lots of other folks have similar questions / concerns. > > First, thank you JP for sharing your method. Indeed--a very good programmatic method for calculating PCR 17. > Upon reading the spec more carefully, I realize that the nested SHA-1 expression for the contents > of PCR-17 is indeed correct: > > SHA-1 ( SinitMleData.SinitHash | SHA-1 ( SinitMleData.BiosAcm.ID | SinitMleData.MsegValid | > SinitMleData.StmHash | SinitMleData.PolicyControl | SinitMleData.LcpPolicyHash | > (OsSinitData.Capabilities, 0) ) ) Whew ;-) > What was not initially clear to me is that SinitMleData.SinitHash is not actually the hash of the > SINIT for a Version 7 SinitMleData. It is the PCR-17 value following the "first extend". As with This is described in the first paragraph of that section: PCR 17 is initialized using the TPM_HASH_START/TPM_HASH_END sequence. The HASH_DATA provided in this sequence is the concatenation of the hash of the SINIT ACM that was used in the launch process and the 4 byte value of the SENTER parameters (in EDX and also in SinitMleData.EdxSenterFlags). As part of this sequence, PCRs 17-23 are reset to 0. The hash of SINIT is also stored in the SinitMleData.SinitHash field. If the SINIT To MLE Data Table (section C.4) version is 7 or greater, the hash of the SINIT ACM is performed using SHA-256, otherwise it uses SHA-1. If a SHA-256 hash was used, the SinitMleData.SinitHash field will contain the value of PCR 17 after the initial extend operation (see below for more details). > a version 6 SinitMleData, there are two extends to PCR-17. The nested SHA-1 expression in the > spec is actually a verbose version of the "second extend". To me, the following is more clear: > > /* first extend (XXX have not confirmed that these inputs are correct XXX) */ > Extend-PCR17 ( sha-256 hash ( SINIT ACM | EdxSenterFlags ) ) This isn't quite correct: first, the TPM_HASH_START/DAT/END sequence isn't exactly the same as TPM_Extend, in that DATA can be more than 160 bits. Second, what is sent as DATA is 'SHA-256(SINIT) | EDX' (i.e. 36 bytes; see above quote from MLE Guide). > /* not an input to either extend, rather an intermediate value to aid in PCR reconstruction post- > launch */ Read PCR17 into SinitMleData.SinitHash > > /* second extend (have successfully confirmed that this is indeed correct) */ > Extend-PCR17(SHA-1 ( SinitMleData.BiosAcm.ID | SinitMleData.MsegValid | SinitMleData.StmHash | > SinitMleData.PolicyControl | SinitMleData.LcpPolicyHash | (OsSinitData.Capabilities, 0) ) > > Once more: The "second extend" is equivalent to the SHA-1 expression listed in the spec. > > Now, I have successfully recomputed the "second extend" taking on faith that > SinitMleData.SinitHash does in fact represent the result of the "first extend" shown above. > However, I don't want to take it on faith. I want to recompute it. What follows is my current > read of the spec, which is so far INCORRECT. However, I still want to detail my thinking here, in > case anybody is able to point out where it goes > wrong: > > The "first extend" listed above: > Extend-PCR17 ( sha-256 hash(SINIT ACM | EdxSenterFlags ) ) ...breaks apart into: > SHA-1(0x00^20 | SHA-1 ( SHA-256 ( SINIT ACM | EdxSenterFlags ) ) ) ... and that result should be > equivalent to the value that I find in SinitMleData.SinitHash. > > Right now the thing that I believe is most likely to be incorrect is the value that I am using for > "SINIT ACM" in the input to sha-256. I am simply using the entire contents of the file > i5_i7_DUAL_SINIT_18.BIN. I suspect I need to parse that file and strip off some metadata. First, you need to adjust your calculation per the comment about 'SHA-256(SINIT) | EDX'. Second, the SHA-256 of SINIT is not performed on the entire binary. Appendix A.1 "alludes" to how the hash is calculated (since it is the same as what is used in the signature): RSASig The PKCS #1.5 RSA Signature of the module. The RSA Signature signs an area that includes the some of the module header and the USER AREA data field (which represents the body of the module). Parts of the module header not included are: the RSA Signature, public key, and scratch field. > I will write in again when if / when I get this figured out. > > In the mean time, thanks for any hints that anybody can provide! > > Regards, > -Jon > > ------------------------------------------------------------------------------ > Why Cloud-Based Security and Archiving Make Sense Osterman Research conducted this study that > outlines how and why cloud computing security and archiving is rapidly being adopted across the IT > space for its ease of implementation, lower cost, and increased reliability. Learn more. > http://www.accelacomm.com/jaw/sfnl/114/51425301/ > _______________________________________________ > tboot-devel mailing list > tbo...@li... > https://lists.sourceforge.net/lists/listinfo/tboot-devel |
From: Jonathan M. <jon...@cm...> - 2011-09-12 20:44:04
|
Hi Joseph, Thanks so much for your detailed reply. I have indeed gotten things to work. For the aid of others, here are some of the useful bits. I may post some more complete code in a week or two. > First, you need to adjust your calculation per the comment about 'SHA-256(SINIT) | EDX'. Second, the SHA-256 of SINIT is not performed on the entire binary. Appendix A.1 "alludes" to how the hash is calculated (since it is the same as what is used in the signature): Indeed, the actual value of PCR 17 after the "first extend" turns out to be: SHA1(0x00^20 | SHA1(SHA256(SINIT**) | EdxSenterFlags)) SINIT** denotes only part of the sinit module, as Joseph suggested. More below. > RSASig > The PKCS #1.5 RSA Signature of the module. The RSA Signature signs an area that includes the some of the module header and the USER AREA data field (which represents the body of the module). Parts of the module header not included are: the RSA Signature, public key, and scratch field. Not including the RSA Signature, Public Key, or Scratch field still leaves a little wiggle room with respect to whether any metadata (e.g., size information) pertaining to those areas is included. Here is what is working for me: I'm using the definition of acm_hdr_t from acmod.h from tboot-1.6, and I created a big binary version of the SINIT of interest in a C array using: 'xxd -i /boot/i5_i7_DUAL_SINIT_18.BIN > i5_i7_DUAL_SINIT_18.h' (As an aside, xxd may be the greatest program you've never heard of ;-). Here is a function that recomputes the PCR-17 value from the "first extend" which should (and does for my tests) match SinitMleData.SinitHash: int validate_pcr17_sinit_hash_version7(sinit_mle_data_t *smd) { SHA_CTX c; unsigned char pcr17[20], inner[20]; EVP_MD_CTX mdctx; const EVP_MD *md; unsigned char md_value[EVP_MAX_MD_SIZE]; int md_len; acm_hdr_t *s = (acm_hdr_t*)i5_i7_DUAL_SINIT_18_BIN; OpenSSL_add_all_digests(); if(!(md = EVP_get_digestbyname("sha256"))) return -1; EVP_MD_CTX_init(&mdctx); EVP_DigestInit_ex(&mdctx, md, NULL); #define HASHIN(foo) EVP_DigestUpdate(&mdctx, &foo, sizeof(foo)); \ printf(" size %d\n", sizeof(foo)); HASHIN(s->module_type); HASHIN(s->module_subtype); HASHIN(s->header_len); HASHIN(s->header_ver); HASHIN(s->chipset_id); HASHIN(s->flags); HASHIN(s->module_vendor); HASHIN(s->date); HASHIN(s->size); HASHIN(s->reserved1); HASHIN(s->code_control); HASHIN(s->error_entry_point); HASHIN(s->gdt_limit); HASHIN(s->gdt_base); HASHIN(s->seg_sel); HASHIN(s->entry_point); EVP_DigestUpdate(&mdctx, s->reserved2, sizeof(s->reserved2)); printf(" size reserved2 %d\n", sizeof(s->reserved2)); HASHIN(s->key_size); HASHIN(s->scratch_size); uint32_t user_area_len = i5_i7_DUAL_SINIT_18_BIN_len - ((uint32_t)s->user_area - (uint32_t)s); printf(" user_area_len %d\n", user_area_len); EVP_DigestUpdate(&mdctx, s->user_area, user_area_len); EVP_DigestFinal_ex(&mdctx, md_value, &md_len); dump_bytes1("sha256(): ", md_value, md_len); EVP_MD_CTX_cleanup(&mdctx); printf(" md_len %d\n", md_len); memset(pcr17, 0, sizeof(sha1_hash_t)); // PCR-17 reset to zero by GETSEC[SENTER] // First compute "inner" SHA-1 (data sent in TPM_HASH_DATA sequence) SHA1_Init(&c); SHA1_Update(&c, md_value, md_len); SHA1_Update(&c, &smd->edx_senter_flags, sizeof(uint32_t)); SHA1_Final(inner, &c); // Second compute Extend(inner) SHA1_Init(&c); SHA1_Update(&c, pcr17, sizeof(sha1_hash_t)); // First part of payload existing 20 zeros SHA1_Update(&c, inner, sizeof(sha1_hash_t)); // Second part is "inner" SHA-1 computed above SHA1_Final(pcr17, &c); // Compute final digest dump_bytes1("pcr17 (1st ext)", pcr17, sizeof(sha1_hash_t)); if(!memcmp(pcr17, smd->sinit_hash, sizeof(sha1_hash_t))) { return 0; /* success */ } return -1; /* failure */ } So once again, thanks Joseph and JP for your responses. JP, hopefully this helps you to no longer take PCR-17 on faith. Best, -Jon |