From: Maksim D. <dk...@bf...> - 2008-01-17 16:58:05
|
Hi, I have the question which I can't resolve myself. The situation is following (the following is client-side): - I have the non-migratable BIND type key on the client - I have created and activated TPM identity key - I have certified the BIND public key with the private portion of the TPM AIK using the TcIRsaKey.certifyKey() method - I have received the TcTssValidation structure that contains the signature Now I need to transfer the AIK public key and BIND key signature to the server and verify the signature of the BIND key using the AIK public key. How can I do it assuming the server has the TPM chip as well? The most reasonable solution I have thought of is signing manually the public BIND key with the public AIK key and comparing the results, but that leaves a question why using the TcIRsaKey.certifyKey() method at all? I can sign the public BIND key with the private AIK key using sign method of the TSS. I would really appreaciate if someone shed the light on the situation for me! Regards, Maksim. |
From: Martin P. <Mar...@ia...> - 2008-01-18 13:59:10
Attachments:
smime.p7s
|
Hi... I'm not quite sure what you want to archive, but I'll try to give some help. You do not seem to be sure which key you want to use for which application. Maksim Djackov wrote: > why using the TcIRsaKey.certifyKey() method at all? For certifying a non-migratable key with an identity key. Quoting TPM specification, command TPM_CertifyKey: "A TPM identity key may be used to certify non-migratable keys but is not= permitted to certify migratory keys or certified migration keys. As such= , it allows the TPM to make the statement =93this key is held in a TPM-shi= elded location, and it will never be revealed.=94 For this statement to have v= eracity, the Challenger must trust the policies used by the entity that issued th= e identity and the maintenance policy of the TPM manufacturer." "When this command is run to certify [...] it will return and sign a TPM_CERTIFY_INFO(2) structure" > I can sign the public BIND key with the private AIK key using sign=20 > method of the TSS. I don't think so. Quoting TPM specification, command TPM_Sign: "The Sign command signs data and returns the resulting digital signature"= "Validate that keyHandle->keyUsage is TPM_KEY_SIGNING or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE" The TCG specs are rather cryptic reading, but if you want an authorative source, you'll have to bite through. > - I have the non-migratable BIND type key on the client > - I have created and activated TPM identity key > - I have certified the BIND public key with the private portion of the > TPM AIK using the TcIRsaKey.certifyKey() method > - I have received the TcTssValidation structure that contains the signa= ture > > Now I need to transfer the AIK public key and BIND key signature to the= > server and verify the signature of the BIND key using the AIK public ke= y. A validator requires 3 data packages * an AIK certificate with the AIK public key * the CERTIFY_INFO_STRUCTURE plain data of the certified key (if he is not able to reconstruct it by other means) * the signature resulting from the certification So you * check correctness of AIK certificate * use AIK public key from certificate to verify signature on raw data blo= ck * check raw data if key fields etc. are as expected > How can I do it assuming the server has the TPM chip as well? There is no need for a TPM for verifying a signature on a block of data. HTH, Martin |
From: Maksim D. <dk...@bf...> - 2008-01-18 21:47:10
|
Thanks a lot. Basically to paraphrase my question: - How can I verify the result of TcIRsaKey.certifyKey() (certify the BIND public key with the AIK private key) command on the other machine, given the AIK public key and the BIND public key? Basically, from your answer I have understood that I must use the Java software to do the verification, extracting needed data fields from the validation result of certifyKey() command. I have to check then what algorthims the certifyKey uses and recreate the command flow. If I am wrong, please, correct me. However, I have another question now as well. This is regarding using the public portion of the key created in the TPM to encrypt information on another machine and decrypt information later on the TPM where the key was created using the private portion of the key. My steps are: 1) Create and load the non-migratable bind type key (this is my custom functions, but you will get the idea): TcIRsaKey bindKey = TPMClientInstance.createLoadKeyWithoutPcr(TcTssConstants.TSS_KEY_SIZE_2048 | TcTssConstants.TSS_KEY_TYPE_BIND); 2) Get the public portion of the key and send it to other machine: TcTpmPubkey pubKeyBind = new TcTpmPubkey(TPMClientInstance.getPubKeyBlob(bindKey)); 3) Encrypt the string using the public key: String plainString = "BAC encoded (The client is okay!)"; TcBlobData encData = TPMClientInstance.encryptMessage(pubKeyBind, TcBlobData.newString(plainString)); Where the encryptMessage() is: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public TcBlobData encryptMessage(TcTpmPubkey pubKey, TcBlobData plainData){ TcBlobData encData = null; try { encData = TcCrypto.pubEncryptRsaEcbPkcs1Padding(pubKey, plainData); } catch (TcTssException e) { System.out.println("Unable to encrypt the blob."); e.printStackTrace(); } return encData; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4) Send the message back and decrypt it using the bind private key: TcBlobData decData = TPMClientInstance.decryptMessage(bindKey, encData); Where decryptMessage is: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public TcBlobData decryptMessage(TcIRsaKey bindKey, TcBlobData encDataBlob){ TcBlobData decDataBlob = null; try { TcIEncData encData = commonInstance.context_.createEncDataObject(TcTssConstants.TSS_ENCDATA_BIND); encData.setAttribData(TcTssConstants.TSS_TSPATTRIB_ENCDATA_BLOB, TcTssConstants.TSS_TSPATTRIB_ENCDATABLOB_BLOB, encDataBlob); decDataBlob = encData.unbind(bindKey); } catch (TcTssException e) { System.out.println("Unable to decrypt the blob."); e.printStackTrace(); } return decDataBlob; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// So you can see that I get a blob after encryption with the help of pubEncryptRsaEcbPkcs1Padding() and decrypt the blob using setAttribData() and unbind(). And I get: ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// iaik.tc.tss.api.exceptions.tcs.TcTpmException: TSS Error: error layer: 0x00 (TPM) error code (without layer): 0x21 error code (full): 0x21 error message: The decryption process did not complete. at iaik.tc.tss.impl.java.tcs.pbg.TcTpmCmdCommon.handleRetCode(Unknown Source) at iaik.tc.tss.impl.java.tcs.pbg.TcTpmCmdStorage.TpmUnBind(Unknown Source) at iaik.tc.tss.impl.java.tcs.tcsi.TcTcsi.TcsipUnBind(Unknown Source) at iaik.tc.tss.impl.java.tsp.tcsbinding.local.TcTcsBindingLocal.TcsipUnBind(Unknown Source) at iaik.tc.tss.impl.java.tsp.internal.TcTspInternal.TspUnBind_Internal(Unknown Source) at iaik.tc.tss.impl.java.tsp.TcEncData.unbind(Unknown Source) at TPMClient.decryptMessage(TPMClient.java:300) at TPMClientTest.main(TPMClientTest.java:104) Exception in thread "main" java.lang.NullPointerException at TPMClientTest.main(TPMClientTest.java:108) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// I don't know if the process I use is make sense at all, but since I do encryption on the other machine using the Java software stack (no TPM), I obviously can't use the bind() method. I am really sorry for this _really long_ email, but I hope you will find some time to review it and point out my mistake! Regards, Maksim. Martin Pirker wrote: > Hi... > > I'm not quite sure what you want to archive, but I'll try to give > some help. You do not seem to be sure which key you want to use > for which application. > > Maksim Djackov wrote: > >> why using the TcIRsaKey.certifyKey() method at all? >> > > For certifying a non-migratable key with an identity key. > > Quoting TPM specification, command TPM_CertifyKey: > > "A TPM identity key may be used to certify non-migratable keys but is not > permitted to certify migratory keys or certified migration keys. As such, > it allows the TPM to make the statement “this key is held in a TPM-shielded > location, and it will never be revealed.” For this statement to have veracity, > the Challenger must trust the policies used by the entity that issued the > identity and the maintenance policy of the TPM manufacturer." > > "When this command is run to certify [...] it will return and sign > a TPM_CERTIFY_INFO(2) structure" > > >> I can sign the public BIND key with the private AIK key using sign >> method of the TSS. >> > > I don't think so. Quoting TPM specification, command TPM_Sign: > > "The Sign command signs data and returns the resulting digital signature" > "Validate that keyHandle->keyUsage is TPM_KEY_SIGNING or TPM_KEY_LEGACY, > if not return the error code TPM_INVALID_KEYUSAGE" > > > The TCG specs are rather cryptic reading, but if you want an > authorative source, you'll have to bite through. > > > >> - I have the non-migratable BIND type key on the client >> - I have created and activated TPM identity key >> - I have certified the BIND public key with the private portion of the >> TPM AIK using the TcIRsaKey.certifyKey() method >> - I have received the TcTssValidation structure that contains the signature >> >> Now I need to transfer the AIK public key and BIND key signature to the >> server and verify the signature of the BIND key using the AIK public key. >> > > A validator requires 3 data packages > * an AIK certificate with the AIK public key > * the CERTIFY_INFO_STRUCTURE plain data of the certified key > (if he is not able to reconstruct it by other means) > * the signature resulting from the certification > > So you > * check correctness of AIK certificate > * use AIK public key from certificate to verify signature on raw data block > * check raw data if key fields etc. are as expected > > > >> How can I do it assuming the server has the TPM chip as well? >> > > There is no need for a TPM for verifying a signature on a block of data. > > > HTH, > Martin > > |
From: Martin P. <Mar...@ia...> - 2008-01-22 09:47:41
Attachments:
smime.p7s
|
Hi... Maksim Djackov wrote: > - How can I verify the result of TcIRsaKey.certifyKey() (certify the > BIND public key with the AIK private key) command on the other machine, > given the AIK public key and the BIND public key? The signature verification stuff works about like this... (from memory, not tested, may be buggy) TPM machine: TcTssValidation certifyResult = bindKey.certifyKey(identityKey, ....); ... = certifyResult.getData(); // plain data ... = certifyResult.getValidationData(); // signature TcBlobData pubBlob = identitykey.getAttribData(TcTssDefines.TSS_TSPATTRIB_KEY_BLOB, TcTssDefines.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY); TcTcpaPubkey pubStruct = new TcTcpaPubkey(pubBlob); ... = pubStruct.getPubKey().getKey(); // public key Verifier side: byte[] aikPubBytes, byte[] signatureBytes, byte[] plainDataBytes, TcBlobData pubKeyBlob = TcBlobData.newByteArray(aikPubBytes); TcBlobData certifySignature = TcBlobData.newByteArray(signatureBytes); TcBlobData plainData = TcBlobData.newByteArray(plainDataBytes); pubKeyBlob.prepend(TcBlobData.newBYTE(((byte) 0))); // BigInteger requires a leading sign-byte RSAPublicKeySpec pubEkSpec = new RSAPublicKeySpec(new BigInteger(pubKeyBlob.asByteArray()),new BigInteger("65537")); // 65537 is TPM default RSAPublicKey pubKeyJava = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(pubEkSpec); TcIContext context = new TcTssLocalCallFactory().newContextObject(); // do not connect context, we need no TPM (only possible with IAIK stack) TcTpmPubkey pubAikStruct = TcCrypto.pubJavaToTpmKey(pubKeyJava); TcIRsaKey pubAik = context.createRsaKeyObject(TcTssConstants.TSS_KEY_EMPTY_KEY); pubAik.setAttribData(TcTssConstants.TSS_TSPATTRIB_KEY_BLOB, TcTssConstants.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, pubAikStruct.getEncoded()); // hmmm... maybe not needed, already set by pubJavaToTpmKey? pubAik.setAttribUint32(TcTssConstants.TSS_TSPATTRIB_KEY_INFO, TcTssConstants.TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TcTssConstants.TSS_ES_NONE); pubAik.setAttribUint32(TcTssConstants.TSS_TSPATTRIB_KEY_INFO, TcTssConstants.TSS_TSPATTRIB_KEYINFO_SIGSCHEME, TcTssConstants.TSS_SS_RSASSAPKCS1V15_SHA1); // do signature verify TcIHash hash = context.createHashObject(TcTssConstants.TSS_HASH_SHA1); hash.setHashValue(certifySignature.sha1()); hash.verifySignature(plainData, pubAik); TODO: check actual content CERTIFY_INFO if as expected > However, I have another question now as well. This is regarding using > the public portion of the key created in the TPM to encrypt information > on another machine and decrypt information later on the TPM where the > key was created using the private portion of the key. Errr... I don't think I've ever thought about that... HTH, Martin |
From: Maksim D. <dk...@bf...> - 2008-01-23 10:35:14
|
Thanks a lot! The example you provided is not so obvious, but after simple modifications I had it working. Here is the my version of the source code: public boolean certificateValidate(TcTssValidation certifyValidationData, TcIRsaKey aikKey, TcIRsaKey bindKey, TcBlobData nonceBlob){ boolean validationSuccesfull = true; try { TcBlobData pubBlob = aikKey.getAttribData(TcTssConstants.TSS_TSPATTRIB_KEY_BLOB, TcTssConstants.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY); TcTpmPubkey pubStruct = new TcTpmPubkey(pubBlob); TcBlobData pubKeyBlob = pubStruct.getPubKey().getKey(); //Since we do not actually transfer the values use the local variables //TcBlobData pubKeyBlob = aikPubKey; TcBlobData plainData = certifyValidationData.getData(); TcBlobData certifySignature = certifyValidationData.getValidationData(); pubKeyBlob.prepend(TcBlobData.newBYTE(((byte) 0))); // BigInteger requires a leading sign-byte RSAPublicKeySpec pubEkSpec = new RSAPublicKeySpec(new BigInteger(pubKeyBlob.asByteArray()),new BigInteger("65537")); // 65537 is TPM default RSAPublicKey pubKeyJava = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(pubEkSpec); TcIContext context = new TcTssLocalCallFactory().newContextObject(); //do not connect context, we need no TPM (only possible with IAIK stack) TcTpmPubkey pubAikStruct = TcCrypto.pubJavaToTpmKey(pubKeyJava); TcIRsaKey pubAik = context.createRsaKeyObject(TcTssConstants.TSS_KEY_EMPTY_KEY); pubAik.setAttribData(TcTssConstants.TSS_TSPATTRIB_KEY_BLOB, TcTssConstants.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, pubAikStruct.getEncoded()); pubAik.setAttribUint32(TcTssConstants.TSS_TSPATTRIB_KEY_INFO, TcTssConstants.TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TcTssConstants.TSS_ES_NONE); pubAik.setAttribUint32(TcTssConstants.TSS_TSPATTRIB_KEY_INFO, TcTssConstants.TSS_TSPATTRIB_KEYINFO_SIGSCHEME, TcTssConstants.TSS_SS_RSASSAPKCS1V15_SHA1); TcIHash hash = context.createHashObject(TcTssConstants.TSS_HASH_SHA1); // This way is obviously wrong //hash.setHashValue(certifySignature.sha1()); //hash.verifySignature(plainData, pubAik); hash.setHashValue(plainData.sha1()); hash.verifySignature(certifySignature, pubAik); /******** * Verify CERTIFY_INFO as expected */ TcTpmCertifyInfo certifiedData = new TcTpmCertifyInfo(plainData); System.out.println (" Certified data: "+ certifiedData.toString()); //Verify the bind public key digests TcBlobData CIKeyDigest = certifiedData.getPubKeyDigest().getDigest(); System.out.println ("Ceritified data public key digest : "+ CIKeyDigest.toHexString()); TcTpmPubkey bindPubKey = new TcTpmPubkey(bindKey.getPubKey()); TcBlobData bindPubKeyDigest = bindPubKey.getPubKey().getKey().sha1(); //System.out.println ("Bind public key : "+ bindPubKey.getPubKey().toString()); System.out.println ("Bind public key digest : "+ bindPubKeyDigest.toHexString()); if (!CIKeyDigest.equals(bindPubKeyDigest)) validationSuccesfull = false; //Verify the nonce TcBlobData CInonce = certifiedData.getData().getNonce(); System.out.println ("Ceritified nonce : "+ CInonce.toHexString()); if (!CInonce.equals(nonceBlob)) validationSuccesfull = false; } catch (TcTssException e) { validationSuccesfull = false; e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return validationSuccesfull; Martin Pirker wrote: > Hi... > > Maksim Djackov wrote: > >> - How can I verify the result of TcIRsaKey.certifyKey() (certify the >> BIND public key with the AIK private key) command on the other machine, >> given the AIK public key and the BIND public key? >> > > > The signature verification stuff works about like this... > (from memory, not tested, may be buggy) > > > TPM machine: > > TcTssValidation certifyResult = bindKey.certifyKey(identityKey, ....); > > ... = certifyResult.getData(); // plain data > ... = certifyResult.getValidationData(); // signature > > > TcBlobData pubBlob = identitykey.getAttribData(TcTssDefines.TSS_TSPATTRIB_KEY_BLOB, TcTssDefines.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY); > TcTcpaPubkey pubStruct = new TcTcpaPubkey(pubBlob); > ... = pubStruct.getPubKey().getKey(); // public key > > > Verifier side: > > byte[] aikPubBytes, > byte[] signatureBytes, > byte[] plainDataBytes, > > TcBlobData pubKeyBlob = TcBlobData.newByteArray(aikPubBytes); > TcBlobData certifySignature = TcBlobData.newByteArray(signatureBytes); > TcBlobData plainData = TcBlobData.newByteArray(plainDataBytes); > > pubKeyBlob.prepend(TcBlobData.newBYTE(((byte) 0))); // BigInteger requires a leading sign-byte > RSAPublicKeySpec pubEkSpec = new RSAPublicKeySpec(new BigInteger(pubKeyBlob.asByteArray()),new BigInteger("65537")); // 65537 is TPM default > RSAPublicKey pubKeyJava = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(pubEkSpec); > > > TcIContext context = new TcTssLocalCallFactory().newContextObject(); > // do not connect context, we need no TPM (only possible with IAIK stack) > > TcTpmPubkey pubAikStruct = TcCrypto.pubJavaToTpmKey(pubKeyJava); > TcIRsaKey pubAik = context.createRsaKeyObject(TcTssConstants.TSS_KEY_EMPTY_KEY); > pubAik.setAttribData(TcTssConstants.TSS_TSPATTRIB_KEY_BLOB, TcTssConstants.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, pubAikStruct.getEncoded()); > > // hmmm... maybe not needed, already set by pubJavaToTpmKey? > pubAik.setAttribUint32(TcTssConstants.TSS_TSPATTRIB_KEY_INFO, TcTssConstants.TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TcTssConstants.TSS_ES_NONE); > pubAik.setAttribUint32(TcTssConstants.TSS_TSPATTRIB_KEY_INFO, TcTssConstants.TSS_TSPATTRIB_KEYINFO_SIGSCHEME, TcTssConstants.TSS_SS_RSASSAPKCS1V15_SHA1); > > // do signature verify > TcIHash hash = context.createHashObject(TcTssConstants.TSS_HASH_SHA1); > hash.setHashValue(certifySignature.sha1()); > hash.verifySignature(plainData, pubAik); > > > TODO: check actual content CERTIFY_INFO if as expected > > > >> However, I have another question now as well. This is regarding using >> the public portion of the key created in the TPM to encrypt information >> on another machine and decrypt information later on the TPM where the >> key was created using the private portion of the key. >> > > Errr... I don't think I've ever thought about that... > > HTH, > Martin > |