From 70504e74237fdad4547a7d7b459c43ea41c9797d Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Fri, 5 Jun 2020 11:54:41 -0400 Subject: [PATCH 1/3] Modified how TPM2 Provisioner pulls down sub module cpr (#255) --- HIRS_ProvisionerTPM2/lib/CPR.CMakeLists.txt.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HIRS_ProvisionerTPM2/lib/CPR.CMakeLists.txt.in b/HIRS_ProvisionerTPM2/lib/CPR.CMakeLists.txt.in index 132a0c4b..7c67b746 100644 --- a/HIRS_ProvisionerTPM2/lib/CPR.CMakeLists.txt.in +++ b/HIRS_ProvisionerTPM2/lib/CPR.CMakeLists.txt.in @@ -4,8 +4,8 @@ project(cpr-download NONE) include(ExternalProject) ExternalProject_Add(cpr - GIT_REPOSITORY https://github.com/whoshuu/cpr - GIT_TAG 1.3.0 + URL https://github.com/whoshuu/cpr/archive/1.3.0.zip + URL_HASH SHA1=d669d94b41ffaa2de478923c35a83074e34fdc12 SOURCE_DIR "${CMAKE_BINARY_DIR}/lib/cpr-src" BINARY_DIR "${CMAKE_BINARY_DIR}/lib/cpr-build" CONFIGURE_COMMAND "" From 6ae5a18f9934618b3380e00ebf2b8982083ec3fa Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Wed, 11 Mar 2020 13:02:43 -0400 Subject: [PATCH 2/3] Implement --create, --attributes, --out, and --help in JCommander Add KeyName (subjectKeyIdentifier) and KeyValue (public key) to KeyInfo element Implement --privateKeyFile and --publicCertificate in JCommander Implement -v in JCommander. Clean up unit tests. Implement support for PKCS1 in CredentialParser class. Truncate # symbol after parsing subject key identifier Close input streams in CredentialParser class Closes #237 --- build.gradle | 2 +- tools/tcg_rim_tool/RimSignCert.pem | 22 + tools/tcg_rim_tool/build.gradle | 3 + tools/tcg_rim_tool/identity_transform.xslt | 10 + tools/tcg_rim_tool/keystore.jks | Bin 2226 -> 2290 bytes tools/tcg_rim_tool/privateRimKey.pem | 28 ++ .../main/java/hirs/swid/CredentialParser.java | 213 ++++++++ .../src/main/java/hirs/swid/Main.java | 80 +-- .../main/java/hirs/swid/SwidTagConstants.java | 50 +- .../main/java/hirs/swid/SwidTagGateway.java | 457 +++++------------- .../main/java/hirs/swid/utils/Commander.java | 355 ++++---------- .../java/hirs/swid/TestSwidTagGateway.java | 58 +-- .../test/resources/generated_no_cert.swidtag | 14 +- .../resources/generated_with_cert.swidtag | 30 +- 14 files changed, 592 insertions(+), 730 deletions(-) create mode 100644 tools/tcg_rim_tool/RimSignCert.pem create mode 100644 tools/tcg_rim_tool/identity_transform.xslt create mode 100644 tools/tcg_rim_tool/privateRimKey.pem create mode 100644 tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java diff --git a/build.gradle b/build.gradle index 26d24f74..ae1424e2 100644 --- a/build.gradle +++ b/build.gradle @@ -119,7 +119,7 @@ subprojects { 'com.fasterxml.jackson.core:jackson-databind:2.6.3', 'com.fasterxml.jackson.core:jackson-annotations:2.6.3'], jadira_usertype: 'org.jadira.usertype:usertype.core:4.0.0.GA', - jcommander: 'com.beust:jcommander:1.35', + jcommander: 'com.beust:jcommander:1.72', joda_time: 'joda-time:joda-time:2.9.4', jstl: [ 'org.apache.taglibs:taglibs-standard-impl:1.2.5', 'org.apache.taglibs:taglibs-standard-spec:1.2.5'], diff --git a/tools/tcg_rim_tool/RimSignCert.pem b/tools/tcg_rim_tool/RimSignCert.pem new file mode 100644 index 00000000..9d37a2fa --- /dev/null +++ b/tools/tcg_rim_tool/RimSignCert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgIJAPB+r6VBhBn5MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwI +UENDbGllbnQxEjAQBgNVBAMMCUV4YW1wbGVDQTAeFw0yMDAzMTExODExMjJaFw0z +MDAxMTgxODExMjJaMFwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UE +CgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxGzAZBgNVBAMMEmV4YW1wbGUu +UklNLnNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKd1lWGk +SRuxAAY2wHag2GVxUk1dZx2PTpfQOflvLeccAVwa8mQhlsRERq+QK8ilj8Xfqs44 +/nBaccZDOjdfIxIUCMfwhGXjxCaqZbgTucNsExDnu4arTGraoAwzHg0cVLiKT/Cx +j9NL4dcMgxRXsPdHfXb0923C7xYd2t2qfW05umgaj7qeQl6c68CFNsGX4JA8rWFQ +ZvvGx5DGlK4KTcjPuQQINs5fxasNKqLY2hq+z82x/rqwr2hmyizD6FpFSyIABPEM +PfB036GEhRwu1WEMkq8yIp2jgRUoFYke9pB3ph9pVow0Hh4mNFSKD4pP41VSKY1n +us83mdkuukPy5o0CAwEAAaNvMG0wHQYDVR0OBBYEFC/euOfQMKIgnaoBhhqWT+3s +8rzBMB8GA1UdIwQYMBaAFEahuO3bpnFf0NLneoo8XW6aw5Y4MAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgbAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA +A4IBAQBl2Bu9xpnHCCeeebjx+ILQXJXBd6q5+NQlV3zzBrf0bleZRtsOmsuFvWQo +KQxsfZuk7QcSvVd/1v8mqwJ0PwbFKQmrhIPWP+iowiBNqpG5PH9YxhpHQ1osOfib +NLOXMhudIQRY0yAgqQf+MOlXYa0stX8gkgftVBDRutuMKyOTf4a6d8TUcbG2Rnyz +O/6S9bq4cPDYLqWRBM+aGN8e00UWTKpBl6/1EU8wkJA6WdllK2e8mVkXUPWYyHTZ +0qQnrYiuLr36ycAznABDzEAoj4tMZbjIAfuscty6Ggzxl1WbyZLI6YzyXALwaYvr +crTLeyFynlKxuCfDnr1SAHDM65BY +-----END CERTIFICATE----- diff --git a/tools/tcg_rim_tool/build.gradle b/tools/tcg_rim_tool/build.gradle index fd331228..15dc4693 100644 --- a/tools/tcg_rim_tool/build.gradle +++ b/tools/tcg_rim_tool/build.gradle @@ -7,6 +7,8 @@ repositories { dependencies { compile libs.minimal_json + compile libs.jcommander + compile libs.bouncy_castle testCompile libs.testng } @@ -17,6 +19,7 @@ jar { ) } from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {} + exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA' } uploadArchives { diff --git a/tools/tcg_rim_tool/identity_transform.xslt b/tools/tcg_rim_tool/identity_transform.xslt new file mode 100644 index 00000000..d249ca61 --- /dev/null +++ b/tools/tcg_rim_tool/identity_transform.xslt @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/tools/tcg_rim_tool/keystore.jks b/tools/tcg_rim_tool/keystore.jks index 1102b2c52673157be8475cf71df10832de6a1e9a..2877d7f4c9d5c1f8d1b80c74e05e60b1e1652a2b 100644 GIT binary patch delta 1701 zcmV;W23q;D5%Lj`Ab-lyZz%u(1p+XF1pY7%1_~<%0R#am0uccL1pows1nMwU4?f)= z{d2+;AXW3*4xbsj3B}Z@iloK5z9z&9ALv8Il}FJZ)6MZt9t(x0RQ#M!_ocq=TfI4R zKLX#Q#fLDi-zcCzYE|-4`V=r8-sjWk&}w;tpBrE442>g`t$!hC;iUc{iwb)%?W2~q zbeWbCC6`p-`Sb#QYBCM6pE~!ji&Qu*=rs-T z_rZL>Dxqe$sDFCBuX28k-c+=eiq--O`#< zZa&2$p5tf8;1v~U4}!&$=@U1t_JQ@}%?W`1W#g~$IdRH!%VcFs9Skz z9IDBOHWHHycZ2GJST8zOq}nl@z&?Lo8aKSy<4EiC&P53EkX9x9G;$9nCDL0}iZ0xf zLW%7?$ba-}pgF&1w9_5-f6?yHPi8C{dJ&#t!!!`-_q_@0wz%JR?vdgtPjcTQ5q5(r z0A%Lq;luL5;Py~)JFux1q@Aw>p$Wf2TE98k3B<#)X2@R^dAXLULtn#xL`IHWwjF7J~tlVVycL9 zGbjO+AgobOtKVc8Vh`t8{acGNCfvXI03GhYQTn|#A8Njn2o-gW*1XAwkWK=Audeg| zuG50uSq{zaU(_}u#SDqP7oNv@c=9n#Qg|@MI-)o7aX()#C0G^>Wc@_08=UOFsVY<4(V$?6 zb^Loy|56twi9ohPiGK-_$*OIUC)U5S_|k-Ys6BQ@^lK*#0+W?>a(7S{R<7cEW3s@y z(%~NJp#r0~vU@<@V(ERO=}D>5eNvyXP=Bu_cY;Zdp2jm&vN(HIm{kK{cuu~TmN@KJ z1>w4I#sjud+x?3jV<3u@W0mM{5gUV$dZpFo$?QuWFuH{hciu?~-krjf{DE*6Wg4r- zK%!D%azbl&YqiyThrM{rPiDx_Sqns7pgB~8z(tAP#`C9vFDa)#bzAzQ-whb#MSrCU z`3MvH5-5lt)M_uXO+(D7;Ag30(ZQs0vh(8Q6~o5JKoqpG;V^AGy5 zr@QAB|6ql!DM#Z0F9yeQ8^TxvaW~6&eX}M163Uk1QrAoFW$K4&@iGPovHzb8kSG(?DD+9Fdqg3RUIP)7%&!q z6h@)A?c1htU(nL$dWt+4eRG8>&C1X$A`AgKrbFzHuett_>FAd&~|R1nd++l(tClYf7P zx_89Xaj~{We6u_LlJ&Z{aPZhJrI7^Bni$_6(?u3cszH~p^$|}nkdQiA*<~wdyqQ@S zQ1zI|blK9RC#{ICF1`B6z%!fxL(D)ZkBdxYxX1zfta9AC8VvE5Rh!9@$mxvoTmtZE vi|cZ<%X=Ymo>H;6C&Qk-QUGww>lTn$eT}17yFMkI*vsR;TdG6yTwCUFwOCLW delta 1637 zcmV-r2AcWu5wa1GAb&7bvKasX1p+XF1pY7%1_~<%0R#am0uccL1pows1nR3ZBP*7y z-j$R1MH?Y^vsBH0jxxv`1IvQz-T#@ceOUb!1qFoq`^^HRIa*|`BeBc`(JAy4yZ~xp z57~uw7;({$$PaGs+`QX5EGD6qrHljDDvj(Nha~wu8&vOwXMc7IJ1%o$Ka_x5vag=Z=zEWuHsn)v1O+!e|P<1^%a_I&Kky)iqw9{VHkBHDxFLC1#lN4axDvrFFkVS8f}ILLQQ zFs2I{Y$Tz4!`)Vsh-iUMm%rb6m^N9$$d-w3VF|L;`xF!XFbw8f5gzj>58(oNrI0;D zP+tpwCTHodp{-F4YcVy&-bDGwe0=2conjHL9zd!oa~54`k?=k%k^F@_gtz+Y$~)&L zmJD7gJAV-lW?3&1TU32X^nI6?&BmB4#sMEd-70^3;qxoAL+mxvz`M7573r6>2?vFi zYAiFcf(!k&aOa-n#vQ*6Y)!5QiZpfjVO>#}Y_zn;{-LBpQD}h{p zTu`w002dytQ*IAUB_=W0dsxG-V-`Jhq!QQ`7j@j^B2XnqM>8 zx&itmMi+qMGk=jdbm^&aG?NwuA{k{c zf&*bNf&xjP0|Eg80to={ey^oLgcM`L@}h{Y7(@}z#?f&- z(~Hy-<}ZeGHqG}g{)f_T8h!t1=?YA8Rrzo5k&a)y(3O!cB7fskaC8ai*$3B2tor>( z7J}bb1EJ*UjjuwN&Z4KXq^h=AA%~2((R#VXvRc^dTWKrZNM;i+G5@T%Dkv-~%K^e; zZ{XdJyL4%#;vA+nBjnXU)*KN7hn_M5Y1;3uu5IPkiZxKx^&Z5M1bTHl2R+S_=F_v~ j@jg0|k^th$=oSbCW7vS-Q&4(1tS=WW(EF7TN~oBafineJ diff --git a/tools/tcg_rim_tool/privateRimKey.pem b/tools/tcg_rim_tool/privateRimKey.pem new file mode 100644 index 00000000..afe282c4 --- /dev/null +++ b/tools/tcg_rim_tool/privateRimKey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCndZVhpEkbsQAG +NsB2oNhlcVJNXWcdj06X0Dn5by3nHAFcGvJkIZbEREavkCvIpY/F36rOOP5wWnHG +Qzo3XyMSFAjH8IRl48QmqmW4E7nDbBMQ57uGq0xq2qAMMx4NHFS4ik/wsY/TS+HX +DIMUV7D3R3129Pdtwu8WHdrdqn1tObpoGo+6nkJenOvAhTbBl+CQPK1hUGb7xseQ +xpSuCk3Iz7kECDbOX8WrDSqi2Noavs/Nsf66sK9oZsosw+haRUsiAATxDD3wdN+h +hIUcLtVhDJKvMiKdo4EVKBWJHvaQd6YfaVaMNB4eJjRUig+KT+NVUimNZ7rPN5nZ +LrpD8uaNAgMBAAECggEAcnG8npd9U0x7HMQMcsZoPaPdwHvF/gCzkLNA+8RM1bZh +A4ZzA5WlCQs0V8Wq9pyXjn7Wp8txsG1PdlT5k2AUgsVoXuR0R4IKyvYHQG9StEjH +GvWURmwJdLlnSg8hSYqEJ/52taNUDO6+MI8fgiaQDd8w0ryF4OCpLy9GJdnfkGYZ +Ayemb3USFUdj/S67NVqxnvAfFMM5FqkKGhkoy7wBRgO6eOeJvoTq8LMiPiponwwF +DW409ZStbrk1f1Oszst/UvFUWA9BdDfeoPmFR61y3eB5zlMQG8Mhr2v5hvkj9TPX +FU4Fm4EzZ1h/60cdWoP6XYCP7F2NqZ8N8u4UBQNAIQKBgQDcGIw5GJEvRF+FFTTR +hYatMRn80DGTVjdT32MgajdKx05OWxBmQsFob34fiSnr0wAXPJeDXG4ruMBE2bSk +EC8rCO08G8ihQoH8x0cvuERe1fpVWk3RWNucVGIiJSEXAIwWrlYZLTfYd5GqBkPE +OQxxo4MtOyqeHmVH1mOywk9ABQKBgQDCxt95luzqQZV9Xl78QQvOIbjOdHLjY23Z +yp8sGt9birL/WZ33TCRgmH1e61BdrSqO7Om/ail2Y59XM5UU6kLbDj0IgmOPTsrJ +JmIVf8r3bKltVUaLePgr4yex7dmtHRH8OkLXKnE0RCO0kCi9kJMB12yE3pWxk+Pu +zztQd3a66QKBgBNJd2g9deONe01fOVyu9clRhzR3ThDaOkj4R2h8xlGgO4V0R3Ce +ovIy6vt6epj2yYg/wAs720+rhfXCmijSXj/ILXnZ+W/gMyHimKNe42boG2LFYhJZ +Vg1R+7OAS3EHlD8ckeDs7Hrkp3gdymx0j1mZ+ZHKIIbwpPFxoRT2IBm9AoGBAI0Z +bIK0puP8psKvPrgWluq42xwUl7XKLaX8dtqIjQ3PqGP7E8g2TJP9Y7UDWrDB5Xas +gZi821R8Ts3o/DKukcgGxIgJjP4f4h9dwug4L1yWRxaBFB2tgHqqj/MBjxMtX/4M +Zqdgg6mNQyBm3lyVAynuWRrX9DE0JYa2cQ2VvVkhAoGBAMBv/oT813w00759PmkO +Uxv3LXTJuYBbq0Rmga25jN3ow8LrGQdSVg7F/af3I5KUF7mLiegDy1pkRfauyXH7 ++WhEqnf86vDrzPpytDMxinWOQZusCqeWHb+nuVTuL3Fv+GxEdwVGYI/7lFJ7B//h +P5rU93ZoYY7sWcGVqaaEkMRU +-----END PRIVATE KEY----- diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java new file mode 100644 index 00000000..96f3fe5a --- /dev/null +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java @@ -0,0 +1,213 @@ +package hirs.swid; + +import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.util.encoders.Base64; + +import java.io.*; +import java.security.*; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; + +/** + * This class parses private key, public key, and certificate for use in their respective java.security objects. + */ +public class CredentialParser { + private static final String X509 = "X.509"; + private static final String JKS = "JKS"; + private static final String PEM = "PEM"; + private static final String PKCS1_HEADER = "-----BEGIN RSA PRIVATE KEY-----"; + private static final String PKCS1_FOOTER = "-----END RSA PRIVATE KEY-----"; + private static final String PKCS8_HEADER = "-----BEGIN PRIVATE KEY-----"; + private static final String PKCS8_FOOTER = "-----END PRIVATE KEY-----"; + private X509Certificate certificate; + private PrivateKey privateKey; + private PublicKey publicKey; + + public X509Certificate getCertificate() { + return certificate; + } + + public PrivateKey getPrivateKey() { + return privateKey; + } + + public PublicKey getPublicKey() { + return publicKey; + } + + public void parseJKSCredentials() { + KeyStore.PrivateKeyEntry privateKeyEntry = + parseKeystorePrivateKey(SwidTagConstants.DEFAULT_KEYSTORE_PATH, + SwidTagConstants.DEFAULT_PRIVATE_KEY_ALIAS, + SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD); + certificate = (X509Certificate) privateKeyEntry.getCertificate(); + privateKey = privateKeyEntry.getPrivateKey(); + publicKey = certificate.getPublicKey(); + } + + public void parsePEMCredentials(String certificateFile, String privateKeyFile) throws FileNotFoundException { + certificate = parsePEMCertificate(certificateFile); + privateKey = parsePEMPrivateKey(privateKeyFile, "RSA"); + publicKey = certificate.getPublicKey(); + } + + /** + * This method returns the X509Certificate found in a PEM file. + * @param filename + * @return + * @throws FileNotFoundException + */ + private X509Certificate parsePEMCertificate(String filename) throws FileNotFoundException { + X509Certificate certificate = null; + FileInputStream fis = null; + BufferedInputStream bis = null; + try { + fis = new FileInputStream(filename); + bis = new BufferedInputStream(fis); + CertificateFactory certificateFactory = CertificateFactory.getInstance(X509); + + while (bis.available() > 0) { + certificate = (X509Certificate) certificateFactory.generateCertificate(bis); + } + + bis.close(); + } catch (CertificateException e) { + System.out.println("Error in certificate factory: " + e.getMessage()); + } catch (IOException e) { + System.out.println("Error reading from input stream: " + e.getMessage()); + } finally { + try { + if (fis != null) { + fis.close(); + } + if (bis != null) { + bis.close(); + } + } catch (IOException e) { + System.out.println("Error closing input stream: " + e.getMessage()); + } + } + + return certificate; + } + + /** + * This method extracts the private key from a PEM file. + * Both PKCS1 and PKCS8 formats are handled. + * Algorithm argument is present to allow handling of multiple encryption algorithms, + * but for now it is always RSA. + * @param filename + * @return + */ + private PrivateKey parsePEMPrivateKey(String filename, String algorithm) { + PrivateKey privateKey = null; + FileInputStream fis = null; + DataInputStream dis = null; + try { + File file = new File(filename); + fis = new FileInputStream(file); + dis = new DataInputStream(fis); + byte[] key = new byte[(int) file.length()]; + dis.readFully(key); + dis.close(); + + String privateKeyStr = new String(key); + if (privateKeyStr.contains(PKCS1_HEADER)) { + privateKey = getPKCS1KeyPair(filename).getPrivate(); + } else if (privateKeyStr.contains(PKCS8_HEADER)) { + privateKeyStr = privateKeyStr.replace(PKCS8_HEADER, ""); + privateKeyStr = privateKeyStr.replace(PKCS8_FOOTER, ""); + + byte[] decodedKey = Base64.decode(privateKeyStr); + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decodedKey); + KeyFactory keyFactory = KeyFactory.getInstance(algorithm); + + privateKey = keyFactory.generatePrivate(spec); + } + } catch (FileNotFoundException e) { + System.out.println("Unable to locate private key file: " + filename); + } catch (NoSuchAlgorithmException e) { + System.out.println("Unable to instantiate KeyFactory with algorithm: " + algorithm); + } catch (IOException e) { + System.out.println("IOException: " + e.getMessage()); + } catch (InvalidKeySpecException e) { + System.out.println("Error instantiating PKCS8EncodedKeySpec object: " + e.getMessage()); + } finally { + try { + if (fis != null) { + fis.close(); + } + if (dis != null) { + dis.close(); + } + } catch (IOException e) { + System.out.println("Error closing input stream: " + e.getMessage()); + } + } + + return privateKey; + } + + /** + * This method reads a PKCS1 keypair from a PEM file. + * @param filename + * @return + */ + private KeyPair getPKCS1KeyPair(String filename) throws IOException { + Security.addProvider(new BouncyCastleProvider()); + PEMParser pemParser = new PEMParser(new FileReader(filename)); + JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); + KeyPair keyPair = converter.getKeyPair((PEMKeyPair) pemParser.readObject()); + + return keyPair; + } + + /** + * This method returns the private key from a JKS keystore. + * @param keystoreFile + * @param alias + * @param password + * @return KeyStore.PrivateKeyEntry + */ + private KeyStore.PrivateKeyEntry parseKeystorePrivateKey(String keystoreFile, String alias, String password) { + KeyStore keystore = null; + KeyStore.PrivateKeyEntry privateKey = null; + try { + keystore = KeyStore.getInstance("JKS"); + keystore.load(new FileInputStream(keystoreFile), password.toCharArray()); + privateKey = (KeyStore.PrivateKeyEntry) keystore.getEntry(alias, + new KeyStore.PasswordProtection(password.toCharArray())); + } catch (FileNotFoundException e) { + System.out.println("Cannot locate keystore " + keystoreFile); + } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException | CertificateException | IOException e) { + e.printStackTrace(); + } + + return privateKey; + } + + /** + * Utility method for extracting the subjectKeyIdentifier from an X509Certificate. + * The subjectKeyIdentifier is stored as a DER-encoded octet and will be converted to a String. + * @return + */ + public String getCertificateSubjectKeyIdentifier() throws IOException { + String decodedValue = null; + byte[] extension = certificate.getExtensionValue(SwidTagConstants.CERTIFICATE_SUBJECT_KEY_IDENTIFIER); + if (extension != null) { + decodedValue = JcaX509ExtensionUtils.parseExtensionValue(extension).toString(); + } + //If there is a # symbol at the beginning of the string, remove it + if (decodedValue.startsWith("#")) { + decodedValue = decodedValue.substring(1); + } + return decodedValue; + } +} diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index 9c83b043..da3baed2 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -1,50 +1,58 @@ package hirs.swid; import hirs.swid.utils.Commander; +import com.beust.jcommander.JCommander; + +import java.io.FileNotFoundException; import java.io.IOException; -/* - * Command-line application for generating and validating SWID tags. - * Input arg: path to *.swidtag file - * - * If an argument is given it will be validated against the schema at http://standards.iso.org/iso/19770/-2/2015/schema.xsd - * If an argument is not given a SWID tag file will be generated. - */ public class Main { public static void main(String[] args) { - Commander commander = new Commander(args); + Commander commander = new Commander(); + JCommander jc = JCommander.newBuilder().addObject(commander).build(); + jc.parse(args); SwidTagGateway gateway = new SwidTagGateway(); - if (commander.hasArguments()) { - // we have arguments to work with - if (commander.isAttributesGiven()) { - gateway.setAttributesFile(commander.getAttributesFile()); - } - if (commander.isKeystoreGiven()) { - gateway.setKeystoreFile(commander.getKeystore()); - } - if (commander.isShowCert()) { - gateway.setShowCert(true); - } - - if (commander.create()) { - // parsing the arguments detected a create parameter (-c) - gateway.generateSwidTag(commander.getCreateOutFile()); - } - if (commander.validate()) { - // parsing the arguments detected a validation parameter (-v) - try { - gateway.validateSwidTag(commander.getValidateFile()); - } catch (IOException e) { - System.out.println("Unable to validate file: " + e.getMessage()); + if (commander.isHelp()) { + jc.usage(); + System.out.println(commander.printHelpExamples()); + } else { + if (!commander.getVerifyFile().isEmpty()) { + System.out.println(commander.toString()); + String verifyFile = commander.getVerifyFile(); + String publicCertificate = commander.getPublicCertificate(); + if (!verifyFile.isEmpty() && !publicCertificate.isEmpty()) { + try { + gateway.validateSwidTag(verifyFile); + } catch (IOException e) { + System.out.println("Error validating RIM file: " + e.getMessage()); + } + } else { + System.out.println("Need both a RIM file to validate and a public certificate to validate with!"); } - } - if (commander.parse()) { - try { - gateway.parsePayload(commander.getParseFile()); - } catch (IOException e) { - System.out.println("Unable to parse file: " + e.getMessage()); + } else { + System.out.println(commander.toString()); + String createType = commander.getCreateType().toUpperCase(); + String attributesFile = commander.getAttributesFile(); + String certificateFile = commander.getPublicCertificate(); + String privateKeyFile = commander.getPrivateKeyFile(); + switch (createType) { + case "BASE": + if (!attributesFile.isEmpty()) { + gateway.setAttributesFile(attributesFile); + } + if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) { + gateway.setDefaultCredentials(false); + gateway.setPemCertificateFile(certificateFile); + gateway.setPemPrivateKeyFile(privateKeyFile); + } + gateway.generateSwidTag(commander.getOutFile()); + break; + case "EVENTLOG": + break; + case "PCR": + break; } } } diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagConstants.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagConstants.java index bad1a213..1e19a0a5 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagConstants.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagConstants.java @@ -20,15 +20,10 @@ public class SwidTagConstants { public static final String SIGNATURE_ALGORITHM_RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; - public static final String SCHEMA_STATEMENT = "ISO/IEC 19770-2:2015 Schema (XSD 1.0) " - + "- September 2015, see http://standards.iso.org/iso/19770/-2/2015/schema.xsd"; public static final String SCHEMA_PACKAGE = "hirs.swid.xjc"; public static final String SCHEMA_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI; public static final String SCHEMA_URL = "swid_schema.xsd"; - public static final String HIRS_SWIDTAG_HEADERS = "hirsSwidTagHeader.properties"; - public static final String EXAMPLE_PROPERTIES = "swidExample.properties"; - public static final String SOFTWARE_IDENTITY = "SoftwareIdentity"; public static final String ENTITY = "Entity"; public static final String LINK = "Link"; @@ -147,48 +142,5 @@ public class SwidTagConstants { "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", "pathSeparator", "n8060"); -//Below properties can probably be deleted - public static final String SOFTWARE_IDENTITY_NAME = "softwareIdentity.name"; - public static final String SOFTWARE_IDENTITY_TAGID = "softwareIdentity.tagId"; - public static final String SOFTWARE_IDENTITY_VERSION = "softwareIdentity.version"; - public static final String SOFTWARE_IDENTITY_CORPUS = "softwareIdentity.corpus"; - public static final String SOFTWARE_IDENTITY_PATCH = "softwareIdentity.patch"; - public static final String SOFTWARE_IDENTITY_SUPPLEMENTAL = "softwareIdentity.supplemental"; - - public static final String ENTITY_NAME = "entity.name"; - public static final String ENTITY_REGID = "entity.regid"; - public static final String ENTITY_ROLE = "entity.role"; - public static final String ENTITY_THUMBPRINT = "entity.thumbprint"; - - public static final String LINK_HREF = "link.href"; - public static final String LINK_REL = "link.rel"; - - public static final String META_PCURILOCAL = "softwareMeta.pcUriLocal"; - public static final String META_BINDINGSPEC = "softwareMeta.bindingSpec"; - public static final String META_BINDINGSPECVERSION = "softwareMeta.bindingSpecVersion"; - public static final String META_PLATFORMMANUFACTURERID = "softwareMeta.platformManufacturerId"; - public static final String META_PLATFORMMANUFACTURERSTR = "softwareMeta.platformManufacturerStr"; - public static final String META_PLATFORMMODEL = "softwareMeta.platformModel"; - public static final String META_COMPONENTCLASS = "softwareMeta.componentClass"; - public static final String META_COMPONENTMANUFACTURER = "softwareMeta.componentManufacturer"; - public static final String META_COMPONENTMANUFACTURERID = "softwareMeta.componentManufacturerId"; - public static final String META_RIMLINKHASH = "softwareMeta.rimLinkHash"; - - public static final String PAYLOAD_ENVVARPREFIX = "n8060.envvarprefix"; - public static final String PAYLOAD_ENVVARSUFFIX = "n8060.envvarsuffix"; - public static final String PAYLOAD_PATHSEPARATOR = "n8060.pathseparator"; - - public static final String DIRECTORY_KEY = "directory.key"; - public static final String DIRECTORY_LOCATION = "directory.location"; - public static final String DIRECTORY_NAME = "directory.name"; - public static final String DIRECTORY_ROOT = "directory.root"; - public static final String FILE_KEY = "file.key"; - public static final String FILE_LOCATION = "file.location"; - public static final String FILE_NAME = "file.name"; - public static final String FILE_ROOT = "file.root"; - public static final String FILE_SIZE = "file.size"; - public static final String FILE_VERSION = "file.version"; - - public static final int PCR_NUMBER = 0; - public static final int PCR_VALUE = 1; + public static final String CERTIFICATE_SUBJECT_KEY_IDENTIFIER = "2.5.29.14"; } diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java index 8673ae36..4fbe8b52 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java @@ -1,18 +1,19 @@ package hirs.swid; -import javax.xml.bind.JAXB; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.UnmarshalException; +import javax.xml.crypto.dsig.keyinfo.*; import javax.xml.transform.OutputKeys; import javax.xml.transform.Source; import javax.xml.transform.TransformerFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; +import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; @@ -29,7 +30,6 @@ import javax.xml.crypto.XMLStructure; import javax.xml.crypto.dsig.CanonicalizationMethod; import javax.xml.crypto.dsig.DigestMethod; import javax.xml.crypto.dsig.Reference; -import javax.xml.crypto.dsig.SignatureMethod; import javax.xml.crypto.dsig.SignedInfo; import javax.xml.crypto.dsig.Transform; import javax.xml.crypto.dsig.XMLSignature; @@ -37,78 +37,48 @@ import javax.xml.crypto.dsig.XMLSignatureException; import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.dom.DOMSignContext; import javax.xml.crypto.dsig.dom.DOMValidateContext; -import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; -import javax.xml.crypto.dsig.keyinfo.KeyInfo; -import javax.xml.crypto.dsig.keyinfo.X509Data; import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; import javax.xml.crypto.dsig.spec.TransformParameterSpec; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.ByteArrayInputStream; import java.io.BufferedReader; import java.io.FileNotFoundException; -import java.io.OutputStream; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; -import java.security.InvalidAlgorithmParameterException; -import java.security.Key; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.UnrecoverableEntryException; -import java.security.cert.CertificateException; +import java.security.*; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Properties; import java.math.BigInteger; -import hirs.swid.utils.CsvParser; -import hirs.swid.utils.HashSwid; -import hirs.swid.xjc.BaseElement; -import hirs.swid.xjc.CanonicalizationMethodType; -import hirs.swid.xjc.DigestMethodType; import hirs.swid.xjc.Directory; import hirs.swid.xjc.Entity; import hirs.swid.xjc.Link; import hirs.swid.xjc.ObjectFactory; import hirs.swid.xjc.ResourceCollection; -import hirs.swid.xjc.ReferenceType; -import hirs.swid.xjc.SignatureType; -import hirs.swid.xjc.SignatureValueType; -import hirs.swid.xjc.SignatureMethodType; -import hirs.swid.xjc.SignedInfoType; import hirs.swid.xjc.SoftwareIdentity; import hirs.swid.xjc.SoftwareMeta; -import hirs.swid.xjc.TransformType; -import hirs.swid.xjc.TransformsType; import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonObject; -import com.eclipsesource.json.JsonObject.Member; -import com.eclipsesource.json.JsonValue; -import com.eclipsesource.json.Location; import com.eclipsesource.json.ParseException; @@ -120,32 +90,16 @@ import com.eclipsesource.json.ParseException; */ public class SwidTagGateway { - private static final QName _DEFAULT_QNAME = new QName( - "http://www.w3.org/2000/09/xmldsig#", "SHA256", "ds"); - private static final QName _SHA1Value_QNAME = new QName( - "http://www.w3.org/2000/09/xmldsig#", "SHA1", "ds"); - private static final QName _SHA384Value_QNAME = new QName( - "http://www.w3.org/2000/09/xmldsig#", "SHA384", "ds"); - private static final QName _SHA512Value_QNAME = new QName( - "http://www.w3.org/2000/09/xmldsig#", "SHA512", "ds"); private static final QName _SHA256_HASH = new QName( "http://www.w3.org/2001/04/xmlenc#sha256", "hash", "SHA256"); - private final ObjectFactory objectFactory = new ObjectFactory(); - private final File generatedFile = new File("generated_swidTag.swidtag"); - private QName hashValue = null; - private JAXBContext jaxbContext; private Marshaller marshaller; private Unmarshaller unmarshaller; private String attributesFile; - /** - * The keystoreFile is used in signXMLDocument() to pass in the keystore path. - * The same method requires the keystore password and the alias of the private key, - * which would need to be passed in if not using the default keystore. - */ - private String keystoreFile; - private boolean showCert; + private boolean defaultCredentials; + private String pemPrivateKeyFile; + private String pemCertificateFile; /** * Default constructor initializes jaxbcontext, marshaller, and unmarshaller @@ -156,8 +110,8 @@ public class SwidTagGateway { marshaller = jaxbContext.createMarshaller(); unmarshaller = jaxbContext.createUnmarshaller(); attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE; - keystoreFile = SwidTagConstants.DEFAULT_KEYSTORE_PATH; - showCert = false; + defaultCredentials = true; + pemCertificateFile = ""; } catch (JAXBException e) { System.out.println("Error initializing jaxbcontext: " + e.getMessage()); } @@ -172,107 +126,37 @@ public class SwidTagGateway { } /** - * Setter for String holding keystore path - * @param keystore + * Setter for boolean governing signing credentials + * @param defaultCredentials + * @return */ - public void setKeystoreFile(String keystoreFile) { - this.keystoreFile = keystoreFile; + public void setDefaultCredentials(boolean defaultCredentials) { + this.defaultCredentials = defaultCredentials; } /** - * Setter for boolean to display certificate block in xml signature - * @param showCert + * Setter for private key file in PEM format + * @param pemPrivateKeyFile */ - public void setShowCert(boolean showCert) { - this.showCert = showCert; + public void setPemPrivateKeyFile(String pemPrivateKeyFile) { + this.pemPrivateKeyFile = pemPrivateKeyFile; } - /** - * default generator method that has no parameters + /** Setter for certificate file in PEM format + * @param pemCertificateFile */ - public void generateSwidTag() { - generateSwidTag(""); - } - - /** - * This generator method is used by the create method. - * - * This method should be updated to incorporate the RIM fields that are implemented - * in generateSwidTag(final File outputFile) below. - * - * @param inputFile - the file in csv format that is used as data - * @param outputFile - output specific to the given file - * @param hashType - the optional labeling of the hash type - */ - public void generateSwidTag(final String inputFile, - final String outputFile, final String hashType) { - // create file instances - File input = new File(inputFile); - File output = new File(outputFile); - List tempList = new LinkedList<>(); - - // I need to go over this again about which needs to be checked. - if (input.exists()) { - // parse the csv file - CsvParser parser = new CsvParser(input); - for (String line : parser.getContent()) { - tempList.add(line); - } - - if (hashType.contains("256")) { - hashValue = _DEFAULT_QNAME; - } else if (hashType.contains("384")) { - hashValue = _SHA384Value_QNAME; - } else if (hashType.contains("512")) { - hashValue = _SHA512Value_QNAME; - } else if (hashType.contains("1")) { - hashValue = _SHA1Value_QNAME; - } else { - hashValue = _DEFAULT_QNAME; - } - - // generate a swid tag - Properties properties = new Properties(); - InputStream is = null; - try { - is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.HIRS_SWIDTAG_HEADERS); - properties.load(is); - - SoftwareIdentity swidTag = createSwidTag(new JsonObject()); - - JAXBElement entity = objectFactory.createSoftwareIdentityEntity(createEntity(new JsonObject())); - swidTag.getEntityOrEvidenceOrLink().add(entity); - - // we should have resources, there for we need a collection - JAXBElement resources = objectFactory.createSoftwareIdentityPayload(createPayload(tempList, hashValue)); - swidTag.getEntityOrEvidenceOrLink().add(resources); - - JAXBElement jaxbe = objectFactory.createSoftwareIdentity(swidTag); - writeSwidTagFile(jaxbe, output); - } catch (IOException e) { - System.out.println("Error reading properties file: "); - e.printStackTrace(); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException ex) { - // ignore - } - } - } - } + public void setPemCertificateFile(String pemCertificateFile) { + this.pemCertificateFile = pemCertificateFile; } /** * This method generates a base RIM from the values in a JSON file. * - * @param outputFile + * @param filename */ public void generateSwidTag(final String filename) { SoftwareIdentity swidTag = null; try { - System.out.println("Reading base rim values from " + attributesFile); BufferedReader jsonIn = Files.newBufferedReader(Paths.get(attributesFile), StandardCharsets.UTF_8); JsonObject configProperties = Json.parse(jsonIn).asObject(); //SoftwareIdentity @@ -318,12 +202,7 @@ public class SwidTagGateway { } Document signedSoftwareIdentity = signXMLDocument(objectFactory.createSoftwareIdentity(swidTag)); - System.out.println("Signature core validity: " + validateSignedXMLDocument(signedSoftwareIdentity)); - if (!filename.isEmpty()) { - writeSwidTagFile(signedSoftwareIdentity, new File(filename)); - } else { - writeSwidTagFile(signedSoftwareIdentity, generatedFile); - } + writeSwidTagFile(signedSoftwareIdentity, filename); } /** @@ -334,51 +213,33 @@ public class SwidTagGateway { * @param path the location of the file to be validated */ public boolean validateSwidTag(String path) throws IOException { - JAXBElement jaxbe = unmarshallSwidTag(path); - SoftwareIdentity swidTag = (SoftwareIdentity) jaxbe.getValue(); - String output = String.format("name: %s;\ntagId: %s\n%s", - swidTag.getName(), swidTag.getTagId(), - SwidTagConstants.SCHEMA_STATEMENT); - System.out.println("SWID Tag found: "); - System.out.println(output); + Document document = unmarshallSwidTag(path); + Element softwareIdentity = (Element) document.getElementsByTagName("SoftwareIdentity").item(0); + StringBuilder si = new StringBuilder("Base RIM detected:\n"); + si.append("SoftwareIdentity name: " + softwareIdentity.getAttribute("name") + "\n"); + si.append("SoftwareIdentity tagId: " + softwareIdentity.getAttribute("tagId") + "\n"); + System.out.println(si.toString()); + System.out.println("Signature core validity: " + validateSignedXMLDocument(document)); return true; } - /** - * This method calls the marshal() method that writes the swidtag data to the output file. - * - * @param jaxbe - * @param outputFile - */ - public void writeSwidTagFile(JAXBElement jaxbe, File outputFile) { - JAXBContext jaxbContext; - try { - jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE); - Marshaller marshaller = jaxbContext.createMarshaller(); - marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); - marshaller.marshal(jaxbe, outputFile); - } catch (JAXBException e) { - System.out.println("Error generating xml: "); - e.printStackTrace(); - } - } - /** * This method writes a Document object out to the file specified by generatedFile. * * @param swidTag */ - public void writeSwidTagFile(Document swidTag, File outputFile) { + public void writeSwidTagFile(Document swidTag, String output) { try { - OutputStream outStream = new FileOutputStream(outputFile); TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); Source source = new DOMSource(swidTag); - System.out.println("Writing to file: " + outputFile.getName()); - transformer.transform(source, new StreamResult(outStream)); - transformer.transform(source, new StreamResult(System.out)); + if (output.isEmpty()) { + transformer.transform(source, new StreamResult(System.out)); + } else { + transformer.transform(source, new StreamResult(new FileOutputStream(output))); + } } catch (FileNotFoundException e) { System.out.println("Unable to write to file: " + e.getMessage()); } catch (TransformerConfigurationException e) { @@ -392,7 +253,7 @@ public class SwidTagGateway { * This method creates SoftwareIdentity element based on the parameters read in from * a properties file. * - * @param properties the Properties object containing parameters from file + * @param jsonObject the Properties object containing parameters from file * @return SoftwareIdentity object created from the properties */ private SoftwareIdentity createSwidTag(JsonObject jsonObject) { @@ -426,7 +287,7 @@ public class SwidTagGateway { * This method creates an Entity object based on the parameters read in from * a properties file. * - * @param properties the Properties object containing parameters from file + * @param jsonObject the Properties object containing parameters from file * @return Entity object created from the properties */ private Entity createEntity(JsonObject jsonObject) { @@ -463,7 +324,7 @@ public class SwidTagGateway { /** * Thsi method creates a Link element based on the parameters read in from a properties * file. - * @param properties the Properties object containing parameters from file + * @param jsonObject the Properties object containing parameters from file * @return Link element created from the properties */ private Link createLink(JsonObject jsonObject) { @@ -483,7 +344,7 @@ public class SwidTagGateway { /** * This method creates a Meta element based on the parameters read in from a properties * file. - * @param properties the Properties object containing parameters from file + * @param jsonObject the Properties object containing parameters from file * @return the Meta element created from the properties */ private SoftwareMeta createSoftwareMeta(JsonObject jsonObject) { @@ -514,15 +375,15 @@ public class SwidTagGateway { /** * This method creates a Payload from the parameters read in from a properties file. * - * @param properties the Properties object containing parameters from file + * @param jsonObject the Properties object containing parameters from file * @return the Payload object created */ private ResourceCollection createPayload(JsonObject jsonObject) { ResourceCollection payload = objectFactory.createResourceCollection(); Map attributes = payload.getOtherAttributes(); - addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARPREFIX, jsonObject.getString(SwidTagConstants.PAYLOAD_ENVVARPREFIX, "")); - addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARSUFFIX, jsonObject.getString(SwidTagConstants.PAYLOAD_ENVVARSUFFIX, "")); - addNonNullAttribute(attributes, SwidTagConstants._N8060_PATHSEPARATOR, jsonObject.getString(SwidTagConstants.PAYLOAD_PATHSEPARATOR, "")); + addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARPREFIX, jsonObject.getString(SwidTagConstants._N8060_ENVVARPREFIX.getLocalPart(), "")); + addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARSUFFIX, jsonObject.getString(SwidTagConstants._N8060_ENVVARSUFFIX.getLocalPart(), "")); + addNonNullAttribute(attributes, SwidTagConstants._N8060_PATHSEPARATOR, jsonObject.getString(SwidTagConstants._N8060_PATHSEPARATOR.getLocalPart(), "")); return payload; } @@ -530,7 +391,7 @@ public class SwidTagGateway { /** * This method creates a Directory from the parameters read in from a properties file. * - * @param properties the Properties object containing parameters from file + * @param jsonObject the Properties object containing parameters from file * @return Directory object created from the properties */ private Directory createDirectory(JsonObject jsonObject) { @@ -540,13 +401,7 @@ public class SwidTagGateway { addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_TYPE, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_TYPE, "")); addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_FORMAT, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_FORMAT, "")); addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_URI_GLOBAL, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_URI_GLOBAL, "")); -/* - directory.setLocation(jsonObject.getString(SwidTagConstants.DIRECTORY_LOCATION)); - String directoryRoot = jsonObject.getString(SwidTagConstants.DIRECTORY_ROOT); - if (!directoryRoot.isEmpty()) { - directory.setRoot(directoryRoot); - } -*/ + return directory; } @@ -554,8 +409,7 @@ public class SwidTagGateway { * This method creates a hirs.swid.xjc.File from three arguments, then calculates * and stores its hash as an attribute in itself. * - * @param filename - * @param location + * @param jsonObject * @return hirs.swid.xjc.File object from File object */ private hirs.swid.xjc.File createFile(JsonObject jsonObject) { @@ -577,32 +431,6 @@ public class SwidTagGateway { } } - /** - * This method creates a Payload from a list of Strings and a hash algorithm. - * The Strings in the list are expected to be in the form of "[PCR_NUMBER],[PCR_VALUE]" - * and the hash algorithm is attached as the file's xml namespace identifier. - * - * @param populate - * @return - */ - private ResourceCollection createPayload(List populate, QName hashStr) { - ResourceCollection rc = objectFactory.createResourceCollection(); - hirs.swid.xjc.File xjcFile = null; - String[] tempArray = null; - - for (String item : populate) { - xjcFile = objectFactory.createFile(); - - tempArray = item.split(","); - - xjcFile.setName(tempArray[SwidTagConstants.PCR_NUMBER]); - xjcFile.getOtherAttributes().put(hashStr, tempArray[SwidTagConstants.PCR_VALUE]); - rc.getDirectoryOrFileOrProcess().add(xjcFile); - } - - return rc; - } - /** * This method signs a SoftwareIdentity with an xmldsig in compatibility mode. * Current assumptions: digest method SHA256, signature method SHA256, enveloped signature @@ -623,34 +451,47 @@ public class SwidTagGateway { sigFactory.newSignatureMethod(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256, null), Collections.singletonList(reference) ); - KeyStore keystore = KeyStore.getInstance("JKS"); - keystore.load(new FileInputStream(keystoreFile), SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD.toCharArray()); - KeyStore.PrivateKeyEntry privateKey = (KeyStore.PrivateKeyEntry) keystore.getEntry(SwidTagConstants.DEFAULT_PRIVATE_KEY_ALIAS, - new KeyStore.PasswordProtection(SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD.toCharArray())); - X509Certificate certificate = (X509Certificate) privateKey.getCertificate(); + List keyInfoElements = new ArrayList(); + KeyInfoFactory kiFactory = sigFactory.getKeyInfoFactory(); - ArrayList x509Content = new ArrayList(); - x509Content.add(certificate.getSubjectX500Principal().getName()); - if (showCert) { + PrivateKey privateKey; + PublicKey publicKey; + CredentialParser cp = new CredentialParser(); + if (defaultCredentials) { + cp.parseJKSCredentials(); + privateKey = cp.getPrivateKey(); + publicKey = cp.getPublicKey(); + } else { + cp.parsePEMCredentials(pemCertificateFile, pemPrivateKeyFile); + X509Certificate certificate = cp.getCertificate(); + privateKey = cp.getPrivateKey(); + publicKey = cp.getPublicKey(); + ArrayList x509Content = new ArrayList(); + x509Content.add(certificate.getSubjectX500Principal().getName()); x509Content.add(certificate); + X509Data data = kiFactory.newX509Data(x509Content); + keyInfoElements.add(data); } - X509Data data = kiFactory.newX509Data(x509Content); - KeyInfo keyinfo = kiFactory.newKeyInfo(Collections.singletonList(data)); + KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier()); + keyInfoElements.add(keyName); + KeyValue keyValue = kiFactory.newKeyValue(publicKey); + keyInfoElements.add(keyValue); + KeyInfo keyinfo = kiFactory.newKeyInfo(keyInfoElements); doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); marshaller.marshal(swidTag, doc); - DOMSignContext context = new DOMSignContext(privateKey.getPrivateKey(), doc.getDocumentElement()); + DOMSignContext context = new DOMSignContext(privateKey, doc.getDocumentElement()); XMLSignature signature = sigFactory.newXMLSignature(signedInfo, keyinfo); signature.sign(context); } catch (FileNotFoundException e) { System.out.println("Keystore not found! " + e.getMessage()); } catch (IOException e) { System.out.println("Error loading keystore: " + e.getMessage()); - } catch (NoSuchAlgorithmException | KeyStoreException | InvalidAlgorithmParameterException | - ParserConfigurationException | UnrecoverableEntryException e) { + } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | + ParserConfigurationException e) { System.out.println(e.getMessage()); - } catch (CertificateException e) { - System.out.println("Certificate error: " + e.getMessage()); + } catch (KeyException e) { + System.out.println("Error setting public key in KeyValue: " + e.getMessage()); } catch (JAXBException e) { System.out.println("Error marshaling signed swidtag: " + e.getMessage()); } catch (MarshalException | XMLSignatureException e) { @@ -733,92 +574,26 @@ public class SwidTagGateway { } /** - * Given an input swidtag at [path] parse any PCRs in the payload into an InputStream object. - * This method will be used in a following pull request. - * - * @param path - * @return - * @throws IOException - */ - public ByteArrayInputStream parsePayload(String path) throws IOException { - JAXBElement jaxbe = unmarshallSwidTag(path); - SoftwareIdentity softwareIdentity = (SoftwareIdentity) jaxbe.getValue(); - String pcrs = ""; - if (!softwareIdentity.getEntityOrEvidenceOrLink().isEmpty()) { - List swidtag = softwareIdentity.getEntityOrEvidenceOrLink(); - for (Object obj : swidtag) { - try { - JAXBElement element = (JAXBElement) obj; - String elementName = element.getName().getLocalPart(); - if (elementName.equals(SwidTagConstants.PAYLOAD)) { - ResourceCollection rc = (ResourceCollection) element.getValue(); - if (!rc.getDirectoryOrFileOrProcess().isEmpty()) { - pcrs = parsePCRs(rc.getDirectoryOrFileOrProcess()); - } - } - } catch (ClassCastException e) { - System.out.println("Found a non-JAXBElement object!" + e.getMessage()); - throw new IOException("Found an invalid element in the swidtag file!"); - } - } - } - return new ByteArrayInputStream(pcrs.getBytes(StandardCharsets.UTF_8)); - } - - /** - * This method traverses a hirs.swid.xjc.Directory recursively until it finds at - * least one hirs.swid.xjc.File. This File is expected to have an attribute of the form - * "[hash algorithm]=[hash value]." - * - * @param list of swidtag elements - * @return the hash value(s) parsed from the File object(s) - */ - private String parsePCRs(List list) { - final String newline = System.lineSeparator(); - StringBuilder sb = new StringBuilder(); - for (Object listItem : list) { - if (listItem instanceof Directory) { - Directory dir = (Directory) listItem; - if (!dir.getDirectoryOrFile().isEmpty()) { - parsePCRs(dir.getDirectoryOrFile()); - } - } else if (listItem instanceof hirs.swid.xjc.File){ - hirs.swid.xjc.File pcr = (hirs.swid.xjc.File) listItem; - String pcrHash = ""; - if (!pcr.getOtherAttributes().isEmpty()) { - Object[] fileAttributes = pcr.getOtherAttributes().values().toArray(); - pcrHash = (String) fileAttributes[0]; - } - if (pcrHash.isEmpty()) { - pcrHash = "null"; - } - sb.append(pcr.getName() + "," + pcrHash); - } - } - System.out.println(sb.toString()); - return sb.toString(); - } - - /** - * This method unmarshalls the swidtag found at [path] into a JAXBElement object + * This method unmarshalls the swidtag found at [path] into a Document object * and validates it according to the schema. * * @param path to the input swidtag * @return the SoftwareIdentity element at the root of the swidtag * @throws IOException if the swidtag cannot be unmarshalled or validated */ - private JAXBElement unmarshallSwidTag(String path) throws IOException { - File input = null; - InputStream is = null; - JAXBElement swidtag = null; - try { - input = new File(path); - is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.SCHEMA_URL); - SchemaFactory schemaFactory = SchemaFactory.newInstance(SwidTagConstants.SCHEMA_LANGUAGE); - Schema schema = schemaFactory.newSchema(new StreamSource(is)); - unmarshaller.setSchema(schema); - swidtag = (JAXBElement) unmarshaller.unmarshal(input); - } catch (SAXException e) { + private Document unmarshallSwidTag(String path) { + InputStream is = null; + Document document = null; + try { + document = removeXMLWhitespace(path); + is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.SCHEMA_URL); + SchemaFactory schemaFactory = SchemaFactory.newInstance(SwidTagConstants.SCHEMA_LANGUAGE); + Schema schema = schemaFactory.newSchema(new StreamSource(is)); + unmarshaller.setSchema(schema); + unmarshaller.unmarshal(document); + } catch (IOException e) { + System.out.println(e.getMessage()); + } catch (SAXException e) { System.out.println("Error setting schema for validation!"); } catch (UnmarshalException e) { System.out.println("Error validating swidtag file!"); @@ -827,18 +602,46 @@ public class SwidTagGateway { } catch (JAXBException e) { e.printStackTrace(); } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - System.out.println("Error closing input stream"); - } - } - if (swidtag != null) { - return swidtag; - } else { - throw new IOException("Invalid swidtag file!"); - } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + System.out.println("Error closing input stream"); + } + } } + + return document; + } + + /** + * This method strips all whitespace from an xml file, including indents and spaces + * added for human-readability. + * @param path + * @return + */ + private Document removeXMLWhitespace(String path) throws IOException { + TransformerFactory tf = TransformerFactory.newInstance(); + Source source = new StreamSource(new File("identity_transform.xslt")); + Document document = null; + File input = new File(path); + if (input.length() > 0) { + try { + Transformer transformer = tf.newTransformer(source); + DOMResult result = new DOMResult(); + transformer.transform(new StreamSource(input), result); + document = (Document) result.getNode(); + } catch (TransformerConfigurationException e) { + System.out.println("Error configuring transformer!"); + e.printStackTrace(); + } catch (TransformerException e) { + System.out.println("Error transforming input!"); + e.printStackTrace(); + } + } else { + throw new IOException("Input file is empty!"); + } + + return document; } } diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index 5c51e167..da380b03 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -6,292 +6,119 @@ import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Paths; +import com.beust.jcommander.Parameter; + /** * Commander is a class that handles the command line arguments for the SWID - * Tags gateway. + * Tags gateway by implementing the JCommander package. */ public class Commander { - private static final String COMMAND_PREFIX = "-"; - private static final String FULL_COMMAND_PREFIX = "--"; - private static final String CREATE_STRING = "create"; - private static final String VERIFY_STRING = "verify"; - private static final String HELP_STRING = "help"; - private static final String PARSE_STRING = "parse"; - private static final String ATTRIBUTES_STRING = "attributes"; - private static final String KEYSTORE_STRING = "keystore"; - private static final String SHOW_CERT_STRING = "show-cert"; - - private boolean hasArguments = false; - private boolean validate = false; - private boolean create = false; - private boolean parse = false; - private boolean attributesGiven = false; - private boolean keystoreGiven = false; - private boolean showCert = false; - - private String validateFile; - private String createOutFile = ""; - private String parseFile; + @Parameter(names = {"-h", "--help"}, help = true, description = "Print this help text.") + private boolean help; + @Parameter(names = {"-c", "--create \"base\""}, order = 0, + description = "The type of RIM to create. A base RIM will be created by default.") + private String createType = "";//other possible values: "eventlog" and "pcr" + @Parameter(names = {"-a", "--attributes "}, order = 1, + description = "The configuration file holding attributes to populate the base RIM with.") private String attributesFile = ""; - private String keystore = ""; - private String hashAlg = null; - - /** - * The main constructor for the Commander class - * - * @param args - */ - public Commander(final String[] args) { - hasArguments = args.length > 0; - - if (hasArguments) { - parseArguments(args); - } else { - printHelp(); - } - - if (create) { - if (hashAlg == null) { - hashAlg = "256"; - } - - if (!getCreateOutFile().isEmpty() && !isValidPath(getCreateOutFile())) { - printHelp(String.format("Invalid file path %s!", getCreateOutFile())); - } - } + @Parameter(names = {"-o", "--out "}, order = 2, + description = "The file to write the RIM out to. The RIM will be written to stdout by default.") + private String outFile = ""; + @Parameter(names = {"-v", "--verify "}, order = 3, + description = "Specify a RIM file to verify.") + private String verifyFile = ""; + @Parameter(names = {"-k", "--privateKeyFile "}, order = 4, + description = "File containing the private key used to sign the base RIM created by the create function.") + private String privateKeyFile = ""; + @Parameter(names = {"-p", "--publicCertificate "}, order = 5, + description = "The public key certificate used to verify a RIM file or to embed in a signed RIM. " + + "A signed RIM generated by this tool by default will not show the signing certificate without this parameter present.") + private String publicCertificate = ""; +/* + @Parameter(names = {"-l", "--rimel "}, order = 6, + description = "The TCG eventlog file to use as a support RIM. By default the last system eventlog will be used.") + private String rimEventLog = ""; + @Parameter(names = {"-t", "--rimpcr "}, order = 7, + description = "The file containing TPM PCR values to use as a support RIM. By default the current platform TPM will be used.") + private String rimPcrs = ""; + //@Parameter(names = {}, order = 8, description = "") + private String toBeSigned = ""; + @Parameter(names = {"-s", "--addSignatureData "}, order = 8, + description = "The signature data in will be combined with the data in " + + "and written to , or will overwrite if is not given.") + private String signatureData = ""; +*/ + public boolean isHelp() { + return help; } - /** - * The default blank constructor - */ - public Commander() { - + public String getCreateType() { + return createType; } - /** - * This method is called if an empty Commander was created, and later gets - * args. Will be used by the main constructor. - * - * @param args - */ - public final void parseArguments(final String[] args) { - String tempValue; - - for (int i = 0; i < args.length; i++) { - tempValue = args[i]; - - switch (tempValue) { - case FULL_COMMAND_PREFIX + CREATE_STRING: - case COMMAND_PREFIX + "c": - create = true; - if (i+1 < args.length && !args[i+1].substring(0,1).equals(COMMAND_PREFIX)) { - createOutFile = args[++i]; - } - break; - case FULL_COMMAND_PREFIX + ATTRIBUTES_STRING: - case COMMAND_PREFIX + "a": - attributesGiven = true; - if (i+1 < args.length && !args[i+1].substring(0,1).equals(COMMAND_PREFIX)) { - attributesFile = args[++i]; - } - break; - case FULL_COMMAND_PREFIX + VERIFY_STRING: - case COMMAND_PREFIX + "v": - validate = true; - validateFile = args[++i]; - break; - case FULL_COMMAND_PREFIX + PARSE_STRING: - case COMMAND_PREFIX + "p": - parse = true; - parseFile = args[++i]; - break; - case FULL_COMMAND_PREFIX + SHOW_CERT_STRING: - showCert = true; - break; - case FULL_COMMAND_PREFIX + HELP_STRING: - case COMMAND_PREFIX + "h": - default: - printHelp(); - } - } - } - - /** - * Getter for the input validate file associated with the validate flag - * - * @return - */ - public final String getValidateFile() { - return validateFile; - } - - /** - * Getter for the output file for the create flag - * - * @return - */ - public final String getCreateOutFile() { - return createOutFile; - } - - /** - * Getter for the property that indicates if something was given at the - * commandline. - * - * @return - */ - public final boolean hasArguments() { - return hasArguments; - } - - /** - * Getter for the validate command flag. - * - * @return - */ - public final boolean validate() { - return validate; - } - - /** - * Getter for the create command flag. - * - * @return - */ - public final boolean create() { - return create; - } - - /** - * Getter for the hash algorithm to be used for hash functions. - * - * @return - */ - public final String getHashAlg() { - return hashAlg; - } - - /** - * Getter for the parse command flag - * - * @return - */ - public final boolean parse() { - return parse; - } - - /** - * Getter for the file to be parsed by the parse command flag - * - * @return - */ - public final String getParseFile() { - return parseFile; - } - - /** - * Getter for the attributes file given flag - * @return - */ - public boolean isAttributesGiven() { - return attributesGiven; - } - - /** - * Getter for the file containing attribute key-value pairs - * @return - */ public String getAttributesFile() { return attributesFile; } - /** - * Getter for the keystore given flag - * @return - */ - public boolean isKeystoreGiven() { - return keystoreGiven; + public String getOutFile() { + return outFile; } - /** - * Getter for the keystore used for digital signatures - * @return - */ - public String getKeystore() { - return keystore; + public String getVerifyFile() { + return verifyFile; } - /** - * Getter for boolean to show certificate data or not - * @return - */ - public boolean isShowCert() { - return showCert; + public String getPrivateKeyFile() { + return privateKeyFile; } - /** - * Default no parameter help method. - */ - private void printHelp() { - printHelp(null); + public String getPublicCertificate() { + return publicCertificate; } - - /** - * This method is used to inform the user of the allowed functionality of - * the program. - */ - private void printHelp(String message) { - StringBuilder sb = new StringBuilder(); - - if (message != null && !message.isEmpty()) { - sb.append(String.format("ERROR: %s\n\n", message)); - } - sb.append("Usage: HIRS_SwidTag\n"); - sb.append(" -c, --create \t\tCreate a base rim and write to\n" - + " \t\t\t\tthe given file. If no file is given the default is\n" - + " \t\t\t\tgenerated_swidTag.swidtag\n\n"); - sb.append(" -a, --attributes \tSpecify the JSON file that contains\n" - + " \t\t\t\tthe xml attributes to add to the RIM\n\n"); - sb.append(" -v, --verify\t\t\tTakes the provided input file and\n" - + " \t\t\t\tvalidates it against the schema at\n" - + " \t\t\t\thttp://standards.iso.org/iso/19770/-2/2015/schema.xsd\n\n"); - sb.append(" -p, --parse \t\tParse the given swidtag's payload\n\n"); /* - sb.append(" -k, --keystore \tSpecify the keystore and its location to use\n" - + " \t\t\t\tfor digital signatures\n"); - */ - sb.append(" --show-cert\t\t\tPrint the certificate in the signature block of\n" - + " \t\t\t\tthe base RIM\n\n"); - sb.append(" -h, --help, \tPrints this command help information.\n"); - sb.append(" \t\t\t\tListing no command arguments will also\n" - + " \t\t\t\tprint this help text.\n\n"); - sb.append("Example commands: \n" - + " Create a base rim from the default attribute file and write the rim\n" - + " to generated_swidTag.swidtag:\n\n" - + " \t\tjava -jar tcg_rim_tool-1.0.jar -c\n\n" - + " Create a base rim from the values in config.json and write the rim\n" - + " to base_rim.swidtag:\n\n" - + " \t\tjava -jar tcg_rim_tool-1.0.jar -c base_rim.swidtag -a config.json\n\n" - + " "); - - System.out.println(sb.toString()); - System.exit(1); + public String getRimEventLog() { + return rimEventLog; } - - /** - * Checks that the file given to create a new swidtag is a valid path. - * @param filepath - * @return - */ - public static boolean isValidPath(String filepath) { - try { - System.out.println("Checking for a valid creation path..."); - File file = new File(filepath); - file.createNewFile(); - } catch (IOException | InvalidPathException | NullPointerException ex) { - return false; - } - return true; + + public String getRimPcrs() { + return rimPcrs; + } + + public String getToBeSigned() { + return toBeSigned; + } + + public String getSignatureData() { + return signatureData; + } +*/ + public String printHelpExamples() { + StringBuilder sb = new StringBuilder(); + sb.append("Create a base RIM using the values in attributes.json; " + + "sign it with the default keystore, alias, and password;\n"); + sb.append("and write the data to base_rim.swidtag:\n\n"); + sb.append("\t\t-c base -a attributes.json -o base_rim.swidtag\n\n\n"); + sb.append("Create a base RIM using the default attribute values; sign it using privateKey.pem;\n"); + sb.append("and write the data to console output, to include cert.pem in the signature block:\n\n"); + sb.append("\t\t-c base -k privateKey.pem -p cert.pem\n\n\n"); + + return sb.toString(); + } + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Creating: " + getCreateType() + System.lineSeparator()); + sb.append("Using attributes file: " + getAttributesFile() + System.lineSeparator()); + sb.append("Write to: " + getOutFile() + System.lineSeparator()); + sb.append("Verify file: " + getVerifyFile() + System.lineSeparator()); + sb.append("Private key file: " + getPrivateKeyFile() + System.lineSeparator()); + sb.append("Public certificate: " + getPublicCertificate() + System.lineSeparator()); +/* + sb.append("Event log support RIM: " + getRimEventLog() + System.lineSeparator()); + sb.append("TPM PCRs support RIM: " + getRimPcrs() + System.lineSeparator()); + sb.append("Base RIM to be signed: " + getToBeSigned() + System.lineSeparator()); + sb.append("External signature file: " + getSignatureData() + System.lineSeparator()); +*/ + return sb.toString(); } } diff --git a/tools/tcg_rim_tool/src/test/java/hirs/swid/TestSwidTagGateway.java b/tools/tcg_rim_tool/src/test/java/hirs/swid/TestSwidTagGateway.java index bee91cf2..793c0ed6 100644 --- a/tools/tcg_rim_tool/src/test/java/hirs/swid/TestSwidTagGateway.java +++ b/tools/tcg_rim_tool/src/test/java/hirs/swid/TestSwidTagGateway.java @@ -14,17 +14,16 @@ import org.testng.annotations.Test; public class TestSwidTagGateway { private SwidTagGateway gateway; - private String inputFile, outputFile, hashType; private final String DEFAULT_OUTPUT = "generated_swidTag.swidtag"; private final String DEFAULT_WITH_CERT = "generated_with_cert.swidtag"; private final String DEFAULT_NO_CERT = "generated_no_cert.swidtag"; + private final String certificateFile = "RimSignCert.pem"; + private final String privateKeyFile = "privateRimKey.pem"; private InputStream expectedFile; @BeforeClass public void setUp() throws Exception { gateway = new SwidTagGateway(); - inputFile = TestSwidTagGateway.class.getClassLoader().getResource("examplecsv.csv").getFile(); - hashType = "SHA256"; } @AfterClass @@ -35,29 +34,35 @@ public class TestSwidTagGateway { } /** - * Creating a base RIM with default attributes with an X509Certificate element. + * This test corresponds to the arguments: + * -c base -k privateRimKey.pem -p RimSignCert.pem */ @Test - public void testGenerateDefaultWithCert() { - gateway.setShowCert(true); - gateway.generateSwidTag(); + public void testCreateBaseWithCert() { + gateway.setDefaultCredentials(false); + gateway.setPemCertificateFile(certificateFile); + gateway.setPemPrivateKeyFile(privateKeyFile); + gateway.generateSwidTag(DEFAULT_OUTPUT); expectedFile = (InputStream) TestSwidTagGateway.class.getClassLoader().getResourceAsStream(DEFAULT_WITH_CERT); Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT)); } /** - * Create a base RIM with default attributes without an X509Certificate element. + * This test corresponds to the arguments: + * -c base + * -c base -a */ @Test - public void testGenerateDefaultNoCert() { - gateway.setShowCert(false); - gateway.generateSwidTag(); + public void testCreateBaseWithoutCert() { + gateway.setDefaultCredentials(true); + gateway.generateSwidTag(DEFAULT_OUTPUT); expectedFile = (InputStream) TestSwidTagGateway.class.getClassLoader().getResourceAsStream(DEFAULT_NO_CERT); Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT)); } /** - * Validate a base RIM with default attributes with an X509Certificate element. + * This test corresponds to the arguments: + * -v -p RimSignCert.pem */ @Test public void testValidateSwidTag() { @@ -68,35 +73,6 @@ public class TestSwidTagGateway { } } - /** - * Verify expected values of a File element in a Payload element. - */ - @Test - public void testParsePayload() { - InputStream is = null; - outputFile = TestSwidTagGateway.class.getClassLoader().getResource(DEFAULT_WITH_CERT).getPath(); - try { - is = gateway.parsePayload(outputFile); - Scanner scanner = new Scanner(is, "UTF-8"); - String test = "Example.com.iotBase.bin,688e293e3ccb522f6cf8a027c9ade7960f84bd0bf3a0b99812bc1fa498a2db8d"; - String temp = ""; - while (scanner.hasNext()) { - temp = scanner.next(); - Assert.assertEquals(temp, test, "temp: " + temp + ", test: " + test); - } - } catch (IOException e) { - Assert.fail("Error parsing test file!"); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - Assert.fail("Failed to close input stream!"); - } - } - } - } - /** * This method compares two files by bytes to determine if they are the same or not. * @param file to be compared to the expected value. diff --git a/tools/tcg_rim_tool/src/test/resources/generated_no_cert.swidtag b/tools/tcg_rim_tool/src/test/resources/generated_no_cert.swidtag index 6269de6b..8887df6c 100644 --- a/tools/tcg_rim_tool/src/test/resources/generated_no_cert.swidtag +++ b/tools/tcg_rim_tool/src/test/resources/generated_no_cert.swidtag @@ -26,9 +26,17 @@ zu3HTmQfeRYs/c6Ck1k3bL1jnyWoNzhBqCuPYrZtPbv9opVP0YOxM5IjRkRgkZIDgYbh1k4WXw8O /iIMZuVJDfKQJSNCTAZsIbUatGDQc/nOihLHdI90wG8zu9amgrl1AEKzH8z864Fan5uuXolfAaak sLJl6RPCNcp+JNCXMMZiS8bmYPQnVJc1ze0I1A== - - CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US - + 2fdeb8e7d030a2209daa01861a964fedecf2bcc1 + + + p3WVYaRJG7EABjbAdqDYZXFSTV1nHY9Ol9A5+W8t5xwBXBryZCGWxERGr5AryKWPxd+qzjj+cFpx +xkM6N18jEhQIx/CEZePEJqpluBO5w2wTEOe7hqtMatqgDDMeDRxUuIpP8LGP00vh1wyDFFew90d9 +dvT3bcLvFh3a3ap9bTm6aBqPup5CXpzrwIU2wZfgkDytYVBm+8bHkMaUrgpNyM+5BAg2zl/Fqw0q +otjaGr7PzbH+urCvaGbKLMPoWkVLIgAE8Qw98HTfoYSFHC7VYQySrzIinaOBFSgViR72kHemH2lW +jDQeHiY0VIoPik/jVVIpjWe6zzeZ2S66Q/LmjQ== + AQAB + + diff --git a/tools/tcg_rim_tool/src/test/resources/generated_with_cert.swidtag b/tools/tcg_rim_tool/src/test/resources/generated_with_cert.swidtag index be75f5a0..336ea344 100644 --- a/tools/tcg_rim_tool/src/test/resources/generated_with_cert.swidtag +++ b/tools/tcg_rim_tool/src/test/resources/generated_with_cert.swidtag @@ -28,23 +28,35 @@ sLJl6RPCNcp+JNCXMMZiS8bmYPQnVJc1ze0I1A== CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US - MIIDYTCCAkmgAwIBAgIJAPB+r6VBhBn4MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAlVTMQsw + MIIDoTCCAomgAwIBAgIJAPB+r6VBhBn5MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAlVTMQsw CQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxEjAQBgNVBAMM -CUV4YW1wbGVDQTAeFw0yMDAyMTAxODE1MzRaFw0yOTEyMTkxODE1MzRaMFwxCzAJBgNVBAYTAlVT +CUV4YW1wbGVDQTAeFw0yMDAzMTExODExMjJaFw0zMDAxMTgxODExMjJaMFwxCzAJBgNVBAYTAlVT MQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxGzAZBgNV BAMMEmV4YW1wbGUuUklNLnNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKd1 lWGkSRuxAAY2wHag2GVxUk1dZx2PTpfQOflvLeccAVwa8mQhlsRERq+QK8ilj8Xfqs44/nBaccZD OjdfIxIUCMfwhGXjxCaqZbgTucNsExDnu4arTGraoAwzHg0cVLiKT/Cxj9NL4dcMgxRXsPdHfXb0 923C7xYd2t2qfW05umgaj7qeQl6c68CFNsGX4JA8rWFQZvvGx5DGlK4KTcjPuQQINs5fxasNKqLY 2hq+z82x/rqwr2hmyizD6FpFSyIABPEMPfB036GEhRwu1WEMkq8yIp2jgRUoFYke9pB3ph9pVow0 -Hh4mNFSKD4pP41VSKY1nus83mdkuukPy5o0CAwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMC -BsAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAGuJ+dasb3/Mb7TBJ1Oe -al5ISq8d2LQD5ke5qnjgSQWKXfQ9fcUy3dWnt3Oked/i8B/Tyk3jCdTZJU3J3iRNgTqFfMLP8rU1 -w2tPYBjjuPKiiK4YRBHPxtFxPdOL1BPmL4ZzNs33Lv6H0m4aff9p6QpMclX5b/CRjl+80JWRLiLj -U3B0CejZB9dJrPr9SBaC31cDoeTpja9Cl86ip7KkqrZZIYeMuNF6ucWyWtjrW2kr3UhmEy8x/6y4 -KigsK8sBwmNv4N2Pu3RppeIcpjYj5NVA1hwRA4eeMgJp2u+urm3l1oo1UNX1HsSSBHp1Owc9zZLm -07Pl8T46kpIA4sroCAU= +Hh4mNFSKD4pP41VSKY1nus83mdkuukPy5o0CAwEAAaNvMG0wHQYDVR0OBBYEFC/euOfQMKIgnaoB +hhqWT+3s8rzBMB8GA1UdIwQYMBaAFEahuO3bpnFf0NLneoo8XW6aw5Y4MAkGA1UdEwQCMAAwCwYD +VR0PBAQDAgbAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQBl2Bu9xpnH +CCeeebjx+ILQXJXBd6q5+NQlV3zzBrf0bleZRtsOmsuFvWQoKQxsfZuk7QcSvVd/1v8mqwJ0PwbF +KQmrhIPWP+iowiBNqpG5PH9YxhpHQ1osOfibNLOXMhudIQRY0yAgqQf+MOlXYa0stX8gkgftVBDR +utuMKyOTf4a6d8TUcbG2RnyzO/6S9bq4cPDYLqWRBM+aGN8e00UWTKpBl6/1EU8wkJA6WdllK2e8 +mVkXUPWYyHTZ0qQnrYiuLr36ycAznABDzEAoj4tMZbjIAfuscty6Ggzxl1WbyZLI6YzyXALwaYvr +crTLeyFynlKxuCfDnr1SAHDM65BY + 2fdeb8e7d030a2209daa01861a964fedecf2bcc1 + + + p3WVYaRJG7EABjbAdqDYZXFSTV1nHY9Ol9A5+W8t5xwBXBryZCGWxERGr5AryKWPxd+qzjj+cFpx +xkM6N18jEhQIx/CEZePEJqpluBO5w2wTEOe7hqtMatqgDDMeDRxUuIpP8LGP00vh1wyDFFew90d9 +dvT3bcLvFh3a3ap9bTm6aBqPup5CXpzrwIU2wZfgkDytYVBm+8bHkMaUrgpNyM+5BAg2zl/Fqw0q +otjaGr7PzbH+urCvaGbKLMPoWkVLIgAE8Qw98HTfoYSFHC7VYQySrzIinaOBFSgViR72kHemH2lW +jDQeHiY0VIoPik/jVVIpjWe6zzeZ2S66Q/LmjQ== + AQAB + + From 8eda518b0adfd2b03652b71bd7a113075a463bc0 Mon Sep 17 00:00:00 2001 From: chubtub <43381989+chubtub@users.noreply.github.com> Date: Mon, 8 Jun 2020 06:50:16 -0400 Subject: [PATCH 3/3] Add exit code 1 for failed validation --- tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index da3baed2..1f93b38c 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -27,9 +27,11 @@ public class Main { gateway.validateSwidTag(verifyFile); } catch (IOException e) { System.out.println("Error validating RIM file: " + e.getMessage()); + System.exit(1); } } else { System.out.println("Need both a RIM file to validate and a public certificate to validate with!"); + System.exit(1); } } else { System.out.println(commander.toString());