Search code examples
javacsha1tpm

Using SHA1 to calculate an aggregate from multiple values


I'm working using the Integrity Measurement Architecture (IMA) (https://sourceforge.net/p/linux-ima/wiki/Home/) and i'm trying to write in Java what they already done in C and explained in the above linked page.

Starting from a list of measurements:

PCR-00: 07274edf7147abda49200100fd668ce2c3a374d7

PCR-01: 48dff4fbf3a34d56a08dfc1504a3a9d707678ff7

PCR-02: 53de584dcef03f6a7dac1a240a835893896f218d

PCR-03: 3a3f780f11a4b49969fcaa80cd6e3957c33b2275

PCR-04: acb44e9dd4594d3f121df2848f572e4d891f0574

PCR-05: df72e880e68a2b52e6b6738bb4244b932e0f1c76

PCR-06: 585e579e48997fee8efd20830c6a841eb353c628

PCR-07: 3a3f780f11a4b49969fcaa80cd6e3957c33b2275

i need to calculate the aggregate of all this measurements. The C code to do this is:

SHA1_Init(&c);
for (i = 0; i < NUM_PCRS; i++) {
    if (DEBUG) {
        printf("PCR-%2.2x: ", i);
        display_sha1_digest(pcr[i].digest);
    }
    SHA1_Update(&c, pcr[i].digest, 20);
}
SHA1_Final(boot_aggregate, &c);

The result using this code is: b5a166c10d153b7cc3e5b4f1eab1f71672b7c524

I writed this java lines to do that:

    String pcr0 = "07274edf7147abda49200100fd668ce2c3a374d7";
    String pcr1 = "48dff4fbf3a34d56a08dfc1504a3a9d707678ff7";
    String pcr2 = "53de584dcef03f6a7dac1a240a835893896f218d";
    String pcr3 = "3a3f780f11a4b49969fcaa80cd6e3957c33b2275";
    String pcr4 = "acb44e9dd4594d3f121df2848f572e4d891f0574";
    String pcr5 = "df72e880e68a2b52e6b6738bb4244b932e0f1c76";
    String pcr6 = "585e579e48997fee8efd20830c6a841eb353c628";
    String pcr7 = "3a3f780f11a4b49969fcaa80cd6e3957c33b2275";
    MessageDigest hash = MessageDigest.getInstance("SHA-1");
    byte[] firstToLastDigest;
    hash.reset();
    hash.update(pcr0.getBytes("UTF-8"));;
    hash.update(pcr1.getBytes("UTF-8"));
    hash.update(pcr2.getBytes("UTF-8"));
    hash.update(pcr3.getBytes("UTF-8"));
    hash.update(pcr4.getBytes("UTF-8"));
    hash.update(pcr5.getBytes("UTF-8"));
    hash.update(pcr6.getBytes("UTF-8"));
    hash.update(pcr7.getBytes("UTF-8"));
    firstToLastDigest = hash.digest();
    digestStr = javax.xml.bind.DatatypeConverter.printHexBinary(firstToLastDigest);
    System.out.println(digestStr);

But i'm getting "EA3487AC70DC445A2E608ED44DC550366F2C6716" instead of the expected result: "b5a166c10d153b7cc3e5b4f1eab1f71672b7c524". Any suggestion?


Solution

  • Note the size in your C program:

    SHA1_Update(&c, pcr[i].digest, 20);
    

    This tells you that the pcr[i].digest is an array of 20 bytes. It is converted to hexadecimal format only for display's sake, but internally, it's just 20 bytes.

    Now what you did is to take the hexadecimal representation of the digest - which is 40 characters long - and put that into the digest. This means that if your PCR digest is 07274edf7..., you take the value of the character 0, the value of the character 7, and so on, and you digest that.

    That is not correct. You should be digesting the values 0x07, 0x27, etc.

    So if all you have are the hexadecimal representations of the values, you should parse it first into a byte array. Not using String.getBytes("UTF-8") - that merely gives you the byte values of the characters in the string! You can probably use javax.xml.bind.DatatypeConverter.parseHexBinary.

    But in a real program, not one where you set up the PCRs as strings, you should already have the 20 byte long arrays that are the result of a previous digest (the value before using printHexBinary). That's the value you are supposed to be updating the digest with.