1 /*
   2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8080462
  27  * @library /test/lib ..
  28  * @modules jdk.crypto.cryptoki
  29  * @run main TestKATForGCM
  30  * @summary Known Answer Test for AES cipher with GCM mode support in
  31  * PKCS11 provider.
  32  */
  33 import java.security.GeneralSecurityException;
  34 import java.security.Provider;
  35 import java.util.Arrays;
  36 import javax.crypto.Cipher;
  37 import javax.crypto.SecretKey;
  38 import javax.crypto.spec.GCMParameterSpec;
  39 import javax.crypto.spec.SecretKeySpec;
  40 
  41 public class TestKATForGCM extends PKCS11Test {
  42 
  43     // Utility methods
  44     private static byte[] HexToBytes(String hexVal) {
  45         if (hexVal == null) return new byte[0];
  46         byte[] result = new byte[hexVal.length()/2];
  47         for (int i = 0; i < result.length; i++) {
  48             // 2 characters at a time
  49             String byteVal = hexVal.substring(2*i, 2*i +2);
  50             result[i] = Integer.valueOf(byteVal, 16).byteValue();
  51         }
  52         return result;
  53     }
  54 
  55     private static class TestVector {
  56         SecretKey key;
  57         byte[] plainText;
  58         byte[] aad;
  59         byte[] cipherText;
  60         byte[] tag;
  61         GCMParameterSpec spec;
  62         String info;
  63 
  64         TestVector(String key, String iv, String pt, String aad,
  65                    String ct, String tag) {
  66             this.key = new SecretKeySpec(HexToBytes(key), "AES");
  67             this.plainText = HexToBytes(pt);
  68             this.aad = HexToBytes(aad);
  69             this.cipherText = HexToBytes(ct);
  70             this.tag = HexToBytes(tag);
  71             this.spec = new GCMParameterSpec(this.tag.length * 8, HexToBytes(iv));
  72             this.info = "key=" + key + ", iv=" + iv + ", pt=" + pt +
  73                 ",aad=" + aad + ", ct=" + ct + ", tag=" + tag;
  74         }
  75 
  76         public String toString() {
  77             return info;
  78         }
  79     }
  80 
  81     // These test vectors are found off NIST's CAVP page
  82     // http://csrc.nist.gov/groups/STM/cavp/index.html
  83     // inside the link named "GCM Test Vectors", i.e.
  84     // http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
  85     // CAVS 14.0, set of test vectors w/ count = 0, keysize = 128
  86     private static TestVector[] testValues = {
  87         // 96-bit iv w/ 128/120/112/104/96-bit tags
  88         // no plain text, no aad
  89         new TestVector("11754cd72aec309bf52f7687212e8957",
  90                        "3c819d9a9bed087615030b65",
  91                        null, null, null,
  92                        "250327c674aaf477aef2675748cf6971"),
  93         new TestVector("272f16edb81a7abbea887357a58c1917",
  94                        "794ec588176c703d3d2a7a07",
  95                        null, null, null,
  96                        "b6e6f197168f5049aeda32dafbdaeb"),
  97         new TestVector("81b6844aab6a568c4556a2eb7eae752f",
  98                        "ce600f59618315a6829bef4d",
  99                        null, null, null,
 100                        "89b43e9dbc1b4f597dbbc7655bb5"),
 101         new TestVector("cde2f9a9b1a004165ef9dc981f18651b",
 102                        "29512c29566c7322e1e33e8e",
 103                        null, null, null,
 104                        "2e58ce7dabd107c82759c66a75"),
 105         new TestVector("b01e45cc3088aaba9fa43d81d481823f",
 106                        "5a2c4a66468713456a4bd5e1",
 107                        null, null, null,
 108                        "014280f944f53c681164b2ff"),
 109         // 96-bit iv w/ 128/120/112/104/96-bit tags
 110         // no plain text, 16-byte aad
 111         new TestVector("77be63708971c4e240d1cb79e8d77feb",
 112                        "e0e00f19fed7ba0136a797f3",
 113                        null,
 114                        "7a43ec1d9c0a5a78a0b16533a6213cab",
 115                        null,
 116                        "209fcc8d3675ed938e9c7166709dd946"),
 117         new TestVector("da0b615656135194ba6d3c851099bc48",
 118                        "d39d4b4d3cc927885090e6c3",
 119                        null,
 120                        "e7e5e6f8dac913036cb2ff29e8625e0e",
 121                        null,
 122                        "ab967711a5770461724460b07237e2"),
 123         new TestVector("7e0986937a88eef894235aba4a2f43b2",
 124                        "92c4a631695907166b422d60",
 125                        null,
 126                        "85c185f8518f9f2cd597a8f9208fc76b",
 127                        null,
 128                        "3bb916b728df94fe9d1916736be1"),
 129         new TestVector("c3db570d7f0c21e86b028f11465d1dc9",
 130                        "f86970f58ceef89fc7cb679e",
 131                        null,
 132                        "c095240708c0f57c288d86090ae34ee1",
 133                        null,
 134                        "e043c52160d652e82c7262fcf4"),
 135         new TestVector("bea48ae4980d27f357611014d4486625",
 136                        "32bddb5c3aa998a08556454c",
 137                        null,
 138                        "8a50b0b8c7654bced884f7f3afda2ead",
 139                        null,
 140                        "8e0f6d8bf05ffebe6f500eb1"),
 141         // 96-bit iv w/ 128/120/112/104/96-bit tags
 142         // no plain text, 20-byte aad
 143         new TestVector("2fb45e5b8f993a2bfebc4b15b533e0b4",
 144                        "5b05755f984d2b90f94b8027",
 145                        null,
 146                        "e85491b2202caf1d7dce03b97e09331c32473941",
 147                        null,
 148                        "c75b7832b2a2d9bd827412b6ef5769db"),
 149         new TestVector("9bf406339fcef9675bbcf156aa1a0661",
 150                        "8be4a9543d40f542abacac95",
 151                        null,
 152                        "7167cbf56971793186333a6685bbd58d47d379b3",
 153                        null,
 154                        "5e7968d7bbd5ba58cfcc750e2ef8f1"),
 155         new TestVector("a2e962fff70fd0f4d63be728b80556fc",
 156                        "1fa7103483de43d09bc23db4",
 157                        null,
 158                        "2a58edf1d53f46e4e7ee5e77ee7aeb60fc360658",
 159                        null,
 160                        "fa37f2dbbefab1451eae1d0d74ca"),
 161         new TestVector("6bf4fdce82926dcdfc52616ed5f23695",
 162                        "cc0f5899a10615567e1193ed",
 163                        null,
 164                        "3340655592374c1da2f05aac3ee111014986107f",
 165                        null,
 166                        "8ad3385cce3b5e7c985908192c"),
 167         new TestVector("4df7a13e43c3d7b66b1a72fac5ba398e",
 168                        "97179a3a2d417908dcf0fb28",
 169                        null,
 170                        "cbb7fc0010c255661e23b07dbd804b1e06ae70ac",
 171                        null,
 172                        "37791edae6c137ea946cfb40"),
 173         // 96-bit iv w/ 128-bit tags, 13/16/32/51-byte plain text, no aad
 174         new TestVector("fe9bb47deb3a61e423c2231841cfd1fb",
 175                        "4d328eb776f500a2f7fb47aa",
 176                        "f1cc3818e421876bb6b8bbd6c9",
 177                        null,
 178                        "b88c5c1977b35b517b0aeae967",
 179                        "43fd4727fe5cdb4b5b42818dea7ef8c9"),
 180         new TestVector("7fddb57453c241d03efbed3ac44e371c",
 181                        "ee283a3fc75575e33efd4887",
 182                        "d5de42b461646c255c87bd2962d3b9a2",
 183                        null,
 184                        "2ccda4a5415cb91e135c2a0f78c9b2fd",
 185                        "b36d1df9b9d5e596f83e8b7f52971cb3"),
 186         new TestVector("9971071059abc009e4f2bd69869db338",
 187                        "07a9a95ea3821e9c13c63251",
 188                        "f54bc3501fed4f6f6dfb5ea80106df0bd836e6826225b75c0222f6e859b35983",
 189                        null,
 190                        "0556c159f84ef36cb1602b4526b12009c775611bffb64dc0d9ca9297cd2c6a01",
 191                        "7870d9117f54811a346970f1de090c41"),
 192         new TestVector("594157ec4693202b030f33798b07176d",
 193                        "49b12054082660803a1df3df",
 194 
 195 "3feef98a976a1bd634f364ac428bb59cd51fb159ec1789946918dbd50ea6c9d594a3a31a5269b0da6936c29d063a5fa2cc8a1c",
 196                       null,
 197 
 198 "c1b7a46a335f23d65b8db4008a49796906e225474f4fe7d39e55bf2efd97fd82d4167de082ae30fa01e465a601235d8d68bc69",
 199                       "ba92d3661ce8b04687e8788d55417dc2"),
 200         // 96-bit iv w/ 128-bit tags, 16-byte plain text, 16/20/48/90-byte aad
 201         new TestVector("c939cc13397c1d37de6ae0e1cb7c423c",
 202                        "b3d8cc017cbb89b39e0f67e2",
 203                        "c3b3c41f113a31b73d9a5cd432103069",
 204                        "24825602bd12a984e0092d3e448eda5f",
 205                        "93fe7d9e9bfd10348a5606e5cafa7354",
 206                        "0032a1dc85f1c9786925a2e71d8272dd"),
 207         new TestVector("d4a22488f8dd1d5c6c19a7d6ca17964c",
 208                        "f3d5837f22ac1a0425e0d1d5",
 209                        "7b43016a16896497fb457be6d2a54122",
 210                        "f1c5d424b83f96c6ad8cb28ca0d20e475e023b5a",
 211                        "c2bd67eef5e95cac27e3b06e3031d0a8",
 212                        "f23eacf9d1cdf8737726c58648826e9c"),
 213         new TestVector("89850dd398e1f1e28443a33d40162664",
 214                        "e462c58482fe8264aeeb7231",
 215                        "2805cdefb3ef6cc35cd1f169f98da81a",
 216 
 217 "d74e99d1bdaa712864eec422ac507bddbe2b0d4633cd3dff29ce5059b49fe868526c59a2a3a604457bc2afea866e7606",
 218                        "ba80e244b7fc9025cd031d0f63677e06",
 219                        "d84a8c3eac57d1bb0e890a8f461d1065"),
 220         new TestVector("bd7c5c63b7542b56a00ebe71336a1588",
 221                        "87721f23ba9c3c8ea5571abc",
 222                        "de15ddbb1e202161e8a79af6a55ac6f3",
 223 
 224 "a6ec8075a0d3370eb7598918f3b93e48444751624997b899a87fa6a9939f844e008aa8b70e9f4c3b1a19d3286bf543e7127bfecba1ad17a5ec53fccc26faecacc4c75369498eaa7d706aef634d0009279b11e4ba6c993e5e9ed9",
 225                        "41eb28c0fee4d762de972361c863bc80",
 226                        "9cb567220d0b252eb97bff46e4b00ff8"),
 227         // 8/1024-bit iv w/ 128-bit tag, no plain text, no aad
 228         new TestVector("1672c3537afa82004c6b8a46f6f0d026",
 229                        "05",
 230                        null, null, null,
 231                        "8e2ad721f9455f74d8b53d3141f27e8e"),
 232         new TestVector("d0f1f4defa1e8c08b4b26d576392027c",
 233 
 234 "42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac",
 235                        null, null, null,
 236                        "7ab49b57ddf5f62c427950111c5c4f0d"),
 237         // 8-bit iv w/ 128-bit tag, 13-byte plain text, 90-byte aad
 238         new TestVector("9f79239f0904eace50784b863e723f6b",
 239                        "d9",
 240                        "bdb0bb10c87965acd34d146171",
 241 
 242 "44db436089327726c5f01139e1f339735c9e85514ccc2f167bad728010fb34a9072a9794c8a5e7361b1d0dbcdc9ac4091e354bb2896561f0486645252e9c78c86beece91bfa4f7cc4a8794ce1f305b1b735efdbf1ed1563c0be0",
 243                        "7e5a7c8dadb3f0c7335b4d9d8d",
 244                        "6b6ef1f53723a89f3bb7c6d043840717"),
 245         // 1024-bit iv w/ 128-bit tag, 51-byte plain text, 48-byte aad
 246         new TestVector("141f1ce91989b07e7eb6ae1dbd81ea5e",
 247 
 248 "49451da24bd6074509d3cebc2c0394c972e6934b45a1d91f3ce1d3ca69e194aa1958a7c21b6f21d530ce6d2cc5256a3f846b6f9d2f38df0102c4791e57df038f6e69085646007df999751e248e06c47245f4cd3b8004585a7470dee1690e9d2d63169a58d243c0b57b3e5b4a481a3e4e8c60007094ef3adea2e8f05dd3a1396f",
 249 
 250 "d384305af2388699aa302f510913fed0f2cb63ba42efa8c5c9de2922a2ec2fe87719dadf1eb0aef212b51e74c9c5b934104a43",
 251 
 252 "630cf18a91cc5a6481ac9eefd65c24b1a3c93396bd7294d6b8ba323951727666c947a21894a079ef061ee159c05beeb4",
 253 
 254 "f4c34e5fbe74c0297313268296cd561d59ccc95bbfcdfcdc71b0097dbd83240446b28dc088abd42b0fc687f208190ff24c0548",
 255                       "dbb93bbb56d0439cd09f620a57687f5d"),
 256     };
 257 
 258     public boolean execute(TestVector[] testValues, Cipher c) throws Exception {
 259         boolean testFailed = false;
 260         for (int i = 0; i < testValues.length; i++) {
 261             try {
 262                 c.init(Cipher.ENCRYPT_MODE, testValues[i].key, testValues[i].spec);
 263                 c.updateAAD(testValues[i].aad);
 264                 byte[] ctPlusTag = c.doFinal(testValues[i].plainText);
 265 
 266                 c.init(Cipher.DECRYPT_MODE, testValues[i].key, testValues[i].spec);
 267                 c.updateAAD(testValues[i].aad);
 268                 byte[] pt = c.doFinal(ctPlusTag); // should fail if tag mismatched
 269 
 270                 // check encryption/decryption results just to be sure
 271                 if (!Arrays.equals(testValues[i].plainText, pt)) {
 272                     System.out.println("PlainText diff failed for test# " + i);
 273                     testFailed = true;
 274                 }
 275                 int ctLen = testValues[i].cipherText.length;
 276                 if (!Arrays.equals(testValues[i].cipherText,
 277                                    Arrays.copyOf(ctPlusTag, ctLen))) {
 278                     System.out.println("CipherText diff failed for test# " + i);
 279                     testFailed = true;
 280                 }
 281                 int tagLen = testValues[i].tag.length;
 282                 if (!Arrays.equals
 283                     (testValues[i].tag,
 284                      Arrays.copyOfRange(ctPlusTag, ctLen, ctLen+tagLen))) {
 285                     System.out.println("Tag diff failed for test# " + i);
 286                     testFailed = true;
 287                 }
 288             } catch (Exception ex) {
 289                 // continue testing other test vectors
 290                 System.out.println("Failed Test Vector: " + testValues[i]);
 291                 ex.printStackTrace();
 292                 testFailed = true;
 293                 continue;
 294             }
 295         }
 296         if (testFailed) {
 297             throw new Exception("Test Failed");
 298         }
 299         // passed all tests...hooray!
 300         return true;
 301     }
 302 
 303     public static void main(String[] args) throws Exception {
 304         main(new TestKATForGCM(), args);
 305     }
 306 
 307     @Override
 308     public void main(Provider p) throws Exception {
 309         Cipher c;
 310         String transformation = "AES/GCM/NoPadding";
 311         try {
 312             c = Cipher.getInstance(transformation, p);
 313         } catch (GeneralSecurityException e) {
 314             System.out.println("Skip testing " + p.getName() +
 315                     ", no support for " + transformation);
 316             return;
 317         }
 318         try {
 319             if (execute(testValues, c)) {
 320                 System.out.println("Test Passed!");
 321             }
 322         } catch (Exception e) {
 323             System.out.println("Exception occured using " + p.getName() + " version " + p.getVersionStr());
 324 
 325             if (isNSS(p)) {
 326                 double ver = getNSSInfo("nss");
 327                 String osName = System.getProperty("os.name");
 328                 if (ver < 3.251d && osName.equals("SunOS")) {
 329                     // buggy behaviour from solaris on 11.2 OS (nss < 3.251)
 330                     System.out.println("Skipping: SunPKCS11-NSS: Old NSS: " + ver);
 331                     return; // OK
 332                 } else if (ver > 3.139 && ver < 3.15 && osName.equals("Linux")) {
 333                     // warn about buggy behaviour on Linux with nss 3.14
 334                     System.out.println("Warning: old NSS " + ver + " might be problematic, consider upgrading it");
 335                 }
 336             }
 337             throw e;
 338         }
 339     }
 340 }
 341