1 /*
   2  * Copyright (c) 2018, 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 8171277
  27  * @summary Test XDH key agreement
  28  * @library /test/lib
  29  * @build jdk.test.lib.Convert
  30  * @run main TestXDH
  31  */
  32 
  33 import java.security.*;
  34 import java.security.spec.*;
  35 import javax.crypto.*;
  36 import java.util.Arrays;
  37 import java.math.BigInteger;
  38 import jdk.test.lib.Convert;
  39 
  40 public class TestXDH {
  41 
  42     public static void main(String[] args) throws Exception {
  43 
  44         runBasicTests();
  45         runKAT();
  46         runSmallOrderTest();
  47         runNonCanonicalTest();
  48         runCurveMixTest();
  49     }
  50 
  51     private static void runBasicTests() throws Exception {
  52         runBasicTest("XDH", null);
  53         runBasicTest("XDH", 255);
  54         runBasicTest("XDH", 448);
  55         runBasicTest("XDH", "X25519");
  56         runBasicTest("XDH", "X448");
  57         runBasicTest("X25519", null);
  58         runBasicTest("X448", null);
  59         runBasicTest("1.3.101.110", null);
  60         runBasicTest("1.3.101.111", null);
  61         runBasicTest("OID.1.3.101.110", null);
  62         runBasicTest("OID.1.3.101.111", null);
  63     }
  64 
  65     private static void runBasicTest(String name, Object param)
  66         throws Exception {
  67 
  68         KeyPairGenerator kpg = KeyPairGenerator.getInstance(name);
  69         if (param instanceof Integer) {
  70             kpg.initialize((Integer) param);
  71         } else if (param instanceof String) {
  72             kpg.initialize(new NamedParameterSpec((String) param));
  73         }
  74         KeyPair kp = kpg.generateKeyPair();
  75 
  76         KeyAgreement ka = KeyAgreement.getInstance(name);
  77         ka.init(kp.getPrivate());
  78         ka.doPhase(kp.getPublic(), true);
  79 
  80         byte[] secret = ka.generateSecret();
  81 
  82         KeyFactory kf = KeyFactory.getInstance(name);
  83         // Test with X509 and PKCS8 key specs
  84         X509EncodedKeySpec pubSpec =
  85             kf.getKeySpec(kp.getPublic(), X509EncodedKeySpec.class);
  86         PKCS8EncodedKeySpec priSpec =
  87             kf.getKeySpec(kp.getPrivate(), PKCS8EncodedKeySpec.class);
  88 
  89         PublicKey pubKey = kf.generatePublic(pubSpec);
  90         PrivateKey priKey = kf.generatePrivate(priSpec);
  91 
  92         ka.init(priKey);
  93         ka.doPhase(pubKey, true);
  94         byte[] secret2 = ka.generateSecret();
  95         if (!Arrays.equals(secret, secret2)) {
  96             throw new RuntimeException("Arrays not equal");
  97         }
  98 
  99         // test with XDH key specs
 100         XECPublicKeySpec xdhPublic =
 101             kf.getKeySpec(kp.getPublic(), XECPublicKeySpec.class);
 102         XECPrivateKeySpec xdhPrivate =
 103             kf.getKeySpec(kp.getPrivate(), XECPrivateKeySpec.class);
 104         PublicKey pubKey2 = kf.generatePublic(xdhPublic);
 105         PrivateKey priKey2 = kf.generatePrivate(xdhPrivate);
 106         ka.init(priKey2);
 107         ka.doPhase(pubKey2, true);
 108         byte[] secret3 = ka.generateSecret();
 109         if (!Arrays.equals(secret, secret3)) {
 110             throw new RuntimeException("Arrays not equal");
 111         }
 112     }
 113 
 114     private static void runSmallOrderTest() throws Exception {
 115         // Ensure that small-order points are rejected
 116 
 117         // X25519
 118         // 0
 119         testSmallOrder(
 120             "X25519",
 121             "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
 122             "0000000000000000000000000000000000000000000000000000000000000000",
 123             "0000000000000000000000000000000000000000000000000000000000000000");
 124         // 1 and -1
 125         testSmallOrder(
 126             "X25519",
 127             "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
 128             "0100000000000000000000000000000000000000000000000000000000000000",
 129             "0000000000000000000000000000000000000000000000000000000000000000");
 130         testSmallOrder(
 131             "X25519",
 132             "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
 133             "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
 134             "0000000000000000000000000000000000000000000000000000000000000000");
 135 
 136         // order 8 points
 137         testSmallOrder(
 138             "X25519",
 139             "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
 140             "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
 141             "0000000000000000000000000000000000000000000000000000000000000000");
 142         testSmallOrder(
 143             "X25519",
 144             "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
 145             "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800",
 146             "0000000000000000000000000000000000000000000000000000000000000000");
 147 
 148         // X448
 149         // 0
 150         testSmallOrder(
 151             "X448",
 152             "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" +
 153             "F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",
 154             "00000000000000000000000000000000000000000000000000000000000000" +
 155             "00000000000000000000000000000000000000000000000000",
 156             "00000000000000000000000000000000000000000000000000000000000000" +
 157             "00000000000000000000000000000000000000000000000000");
 158         // 1 and -1
 159         testSmallOrder(
 160             "X448",
 161             "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" +
 162             "F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",
 163             "01000000000000000000000000000000000000000000000000000000000000" +
 164             "00000000000000000000000000000000000000000000000000",
 165             "00000000000000000000000000000000000000000000000000000000000000" +
 166             "00000000000000000000000000000000000000000000000000");
 167         testSmallOrder(
 168             "X448",
 169             "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BAF" +
 170             "574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",
 171             "fefffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff" +
 172             "fffffffffffffffffffffffffffffffffffffffffffffffff",
 173             "000000000000000000000000000000000000000000000000000000000000000" +
 174             "0000000000000000000000000000000000000000000000000");
 175     }
 176 
 177     private static void testSmallOrder(String name, String a_pri,
 178             String b_pub, String result) throws Exception {
 179 
 180         try {
 181             runDiffieHellmanTest(name, a_pri, b_pub, result);
 182         } catch (InvalidKeyException ex) {
 183             return;
 184         }
 185 
 186         throw new RuntimeException("No exception on small-order point");
 187     }
 188 
 189     private static void runNonCanonicalTest() throws Exception {
 190         // Test non-canonical values
 191 
 192         // high bit of public key set
 193         // X25519
 194         runDiffieHellmanTest(
 195             "X25519",
 196             "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
 197             "DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B8F",
 198             "954e472439316f118ae158b65619eecff9e6bcf51ab29add66f3fd088681e233");
 199 
 200         runDiffieHellmanTest(
 201             "302e020100300706032b656e0500042077076d0a7318a57d3c16c17251b266" +
 202             "45df4c2f87ebc0992ab177fba51db92c2a",
 203             "302c300706032b656e0500032100de9edb7d7b7dc1b4d35b61c2ece435373f" +
 204             "8343c85b78674dadfc7e146f882b8f",
 205             "954e472439316f118ae158b65619eecff9e6bcf51ab29add66f3fd088681e233");
 206 
 207         // large public key
 208 
 209         // X25519
 210         // public key value is 2^255-2
 211         runDiffieHellmanTest(
 212             "X25519",
 213             "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
 214             "FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F",
 215             "81a02a45014594332261085128959869fc0540c6b12380f51db4b41380de2c2c");
 216 
 217         runDiffieHellmanTest(
 218             "302e020100300706032b656e0500042077076d0a7318a57d3c16c17251b266" +
 219             "45df4c2f87ebc0992ab177fba51db92c2a",
 220             "302c300706032b656e0500032100FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
 221             "FFFFFFFFFFFFFFFFFFFFFFFFFFFF7F",
 222             "81a02a45014594332261085128959869fc0540c6b12380f51db4b41380de2c2c");
 223 
 224         // X448
 225         // public key value is 2^448-2
 226         runDiffieHellmanTest(
 227             "X448",
 228             "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" +
 229             "F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",
 230             "FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
 231             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
 232             "66e2e682b1f8e68c809f1bb3e406bd826921d9c1a5bfbfcbab7ae72feecee6" +
 233             "3660eabd54934f3382061d17607f581a90bdac917a064959fb");
 234 
 235         runDiffieHellmanTest(
 236             "3046020100300706032B656F050004389A8F4925D1519F5775CF46B04B5800" +
 237             "D4EE9EE8BAE8BC5565D498C28DD9C9BAF574A9419744897391006382A6F127" +
 238             "AB1D9AC2D8C0A598726B",
 239             "3044300706032B656F0500033900FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
 240             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
 241             "FFFFFFFFFFFFFFFF",
 242             "66e2e682b1f8e68c809f1bb3e406bd826921d9c1a5bfbfcbab7ae72feecee6" +
 243             "3660eabd54934f3382061d17607f581a90bdac917a064959fb");
 244 
 245     }
 246 
 247     private static void runKAT() throws Exception {
 248         // Test both sides of the key exchange using vectors in RFC 7748
 249 
 250         // X25519
 251         // raw
 252         runDiffieHellmanTest(
 253             "X25519",
 254             "77076D0A7318A57D3C16C17251B26645DF4C2F87EBC0992AB177FBA51DB92C2A",
 255             "DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B4F",
 256             "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
 257 
 258         runDiffieHellmanTest(
 259             "X25519",
 260             "5DAB087E624A8A4B79E17F8B83800EE66F3BB1292618B6FD1C2F8B27FF88E0EB",
 261             "8520F0098930A754748B7DDCB43EF75A0DBF3A0D26381AF4EBA4A98EAA9B4E6A",
 262             "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
 263 
 264         // encoded
 265         runDiffieHellmanTest(
 266             "302E020100300706032B656E0500042077076D0A7318A57D3C16C17251B266" +
 267             "45DF4C2F87EBC0992AB177FBA51DB92C2A",
 268             "302C300706032B656E0500032100DE9EDB7D7B7DC1B4D35B61C2ECE435373F" +
 269             "8343C85B78674DADFC7E146F882B4F",
 270             "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
 271 
 272         runDiffieHellmanTest(
 273             "302E020100300706032B656E050004205DAB087E624A8A4B79E17F8B83800E" +
 274             "E66F3BB1292618B6FD1C2F8B27FF88E0EB",
 275             "302C300706032B656E05000321008520F0098930A754748B7DDCB43EF75A0D" +
 276             "BF3A0D26381AF4EBA4A98EAA9B4E6A",
 277             "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
 278 
 279         // X448
 280         //raw
 281         runDiffieHellmanTest(
 282             "X448",
 283             "9A8F4925D1519F5775CF46B04B5800D4EE9EE8BAE8BC5565D498C28DD9C9BA" +
 284             "F574A9419744897391006382A6F127AB1D9AC2D8C0A598726B",
 285             "3EB7A829B0CD20F5BCFC0B599B6FECCF6DA4627107BDB0D4F345B43027D8B9" +
 286             "72FC3E34FB4232A13CA706DCB57AEC3DAE07BDC1C67BF33609",
 287             "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" +
 288             "56fd2464c335543936521c24403085d59a449a5037514a879d");
 289 
 290         runDiffieHellmanTest(
 291             "X448",
 292             "1C306A7AC2A0E2E0990B294470CBA339E6453772B075811D8FAD0D1D6927C1" +
 293             "20BB5EE8972B0D3E21374C9C921B09D1B0366F10B65173992D",
 294             "9B08F7CC31B7E3E67D22D5AEA121074A273BD2B83DE09C63FAA73D2C22C5D9" +
 295             "BBC836647241D953D40C5B12DA88120D53177F80E532C41FA0",
 296             "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" +
 297             "56fd2464c335543936521c24403085d59a449a5037514a879d");
 298 
 299         //encoded
 300         runDiffieHellmanTest(
 301             "3046020100300706032B656F050004389A8F4925D1519F5775CF46B04B5800" +
 302             "D4EE9EE8BAE8BC5565D498C28DD9C9BAF574A9419744897391006382A6F127" +
 303             "AB1D9AC2D8C0A598726B",
 304             "3044300706032B656F05000339003EB7A829B0CD20F5BCFC0B599B6FECCF6D" +
 305             "A4627107BDB0D4F345B43027D8B972FC3E34FB4232A13CA706DCB57AEC3DAE" +
 306             "07BDC1C67BF33609",
 307             "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" +
 308             "56fd2464c335543936521c24403085d59a449a5037514a879d");
 309 
 310         runDiffieHellmanTest(
 311             "3046020100300706032B656F050004381C306A7AC2A0E2E0990B294470CBA3" +
 312             "39E6453772B075811D8FAD0D1D6927C120BB5EE8972B0D3E21374C9C921B09" +
 313             "D1B0366F10B65173992D",
 314             "3044300706032B656F05000339009B08F7CC31B7E3E67D22D5AEA121074A27" +
 315             "3BD2B83DE09C63FAA73D2C22C5D9BBC836647241D953D40C5B12DA88120D53" +
 316             "177F80E532C41FA0",
 317             "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b" +
 318             "56fd2464c335543936521c24403085d59a449a5037514a879d");
 319     }
 320 
 321     private static void runDiffieHellmanTest(String a_pri,
 322         String b_pub, String result) throws Exception {
 323 
 324         KeyFactory kf = KeyFactory.getInstance("XDH");
 325         byte[] a_pri_ba = Convert.hexStringToByteArray(a_pri);
 326         KeySpec privateSpec = new PKCS8EncodedKeySpec(a_pri_ba);
 327         PrivateKey privateKey = kf.generatePrivate(privateSpec);
 328         byte[] b_pub_ba = Convert.hexStringToByteArray(b_pub);
 329         KeySpec publicSpec = new X509EncodedKeySpec(b_pub_ba);
 330         PublicKey publicKey = kf.generatePublic(publicSpec);
 331 
 332         KeyAgreement ka = KeyAgreement.getInstance("XDH");
 333         ka.init(privateKey);
 334         ka.doPhase(publicKey, true);
 335 
 336         byte[] sharedSecret = ka.generateSecret();
 337         byte[] expectedResult = Convert.hexStringToByteArray(result);
 338         if (!Arrays.equals(sharedSecret, expectedResult)) {
 339             throw new RuntimeException("fail: expected=" + result + ", actual="
 340                 + Convert.byteArrayToHexString(sharedSecret));
 341         }
 342 
 343     }
 344 
 345     private static void runDiffieHellmanTest(String curveName, String a_pri,
 346         String b_pub, String result) throws Exception {
 347 
 348         NamedParameterSpec paramSpec = new NamedParameterSpec(curveName);
 349         KeyFactory kf = KeyFactory.getInstance("XDH");
 350         KeySpec privateSpec = new XECPrivateKeySpec(paramSpec,
 351             Convert.hexStringToByteArray(a_pri));
 352         PrivateKey privateKey = kf.generatePrivate(privateSpec);
 353         boolean clearHighBit = curveName.equals("X25519");
 354         KeySpec publicSpec = new XECPublicKeySpec(paramSpec,
 355             Convert.hexStringToBigInteger(clearHighBit, b_pub));
 356         PublicKey publicKey = kf.generatePublic(publicSpec);
 357 
 358         byte[] encodedPrivateKey = privateKey.getEncoded();
 359         System.out.println("Encoded private: " +
 360             Convert.byteArrayToHexString(encodedPrivateKey));
 361         byte[] encodedPublicKey = publicKey.getEncoded();
 362         System.out.println("Encoded public: " +
 363             Convert.byteArrayToHexString(encodedPublicKey));
 364 
 365         KeyAgreement ka = KeyAgreement.getInstance("XDH");
 366         ka.init(privateKey);
 367         ka.doPhase(publicKey, true);
 368 
 369         byte[] sharedSecret = ka.generateSecret();
 370         byte[] expectedResult = Convert.hexStringToByteArray(result);
 371         if (!Arrays.equals(sharedSecret, expectedResult)) {
 372             throw new RuntimeException("fail: expected=" + result + ", actual="
 373                 + Convert.byteArrayToHexString(sharedSecret));
 374         }
 375     }
 376 
 377     /*
 378      * Ensure that SunEC rejects parameters/points for the wrong curve
 379      * when the algorithm ID for a specific curve is specified.
 380      */
 381     private static void runCurveMixTest() throws Exception {
 382         runCurveMixTest("SunEC", "X25519", 448);
 383         runCurveMixTest("SunEC", "X25519", "X448");
 384         runCurveMixTest("SunEC", "X448", 255);
 385         runCurveMixTest("SunEC", "X448", "X25519");
 386     }
 387 
 388     private static void runCurveMixTest(String providerName, String name,
 389                                         Object param) throws Exception {
 390 
 391         KeyPairGenerator kpg = KeyPairGenerator.getInstance(name,
 392             providerName);
 393 
 394         try {
 395             if (param instanceof Integer) {
 396                 kpg.initialize((Integer) param);
 397             } else if (param instanceof String) {
 398                 kpg.initialize(new NamedParameterSpec((String) param));
 399             }
 400             throw new RuntimeException(name + " KeyPairGenerator accepted "
 401                 + param.toString() + " parameters");
 402         } catch (InvalidParameterException ex) {
 403             // expected
 404         }
 405 
 406         // the rest of the test uses the parameter as an algorithm name to
 407         // produce keys
 408         if (param instanceof Integer) {
 409             return;
 410         }
 411         String otherName = (String) param;
 412         KeyPairGenerator otherKpg = KeyPairGenerator.getInstance(otherName,
 413             providerName);
 414         KeyPair otherKp = otherKpg.generateKeyPair();
 415 
 416         // ensure the KeyFactory rejects incorrect keys
 417         KeyFactory kf = KeyFactory.getInstance(name, providerName);
 418         try {
 419             kf.getKeySpec(otherKp.getPublic(), XECPublicKeySpec.class);
 420             throw new RuntimeException(name + " KeyFactory accepted "
 421                 + param.toString() + " key");
 422         } catch (InvalidKeySpecException ex) {
 423             // expected
 424         }
 425         try {
 426             kf.getKeySpec(otherKp.getPrivate(), XECPrivateKeySpec.class);
 427             throw new RuntimeException(name + " KeyFactory accepted "
 428                 + param.toString() + " key");
 429         } catch (InvalidKeySpecException ex) {
 430             // expected
 431         }
 432 
 433         try {
 434             kf.translateKey(otherKp.getPublic());
 435             throw new RuntimeException(name + " KeyFactory accepted "
 436                 + param.toString() + " key");
 437         } catch (InvalidKeyException ex) {
 438             // expected
 439         }
 440         try {
 441             kf.translateKey(otherKp.getPrivate());
 442             throw new RuntimeException(name + " KeyFactory accepted "
 443                 + param.toString() + " key");
 444         } catch (InvalidKeyException ex) {
 445             // expected
 446         }
 447 
 448         KeyFactory otherKf = KeyFactory.getInstance(otherName, providerName);
 449         XECPublicKeySpec otherPubSpec = otherKf.getKeySpec(otherKp.getPublic(),
 450             XECPublicKeySpec.class);
 451         try {
 452             kf.generatePublic(otherPubSpec);
 453             throw new RuntimeException(name + " KeyFactory accepted "
 454                 + param.toString() + " key");
 455         } catch (InvalidKeySpecException ex) {
 456             // expected
 457         }
 458         XECPrivateKeySpec otherPriSpec =
 459             otherKf.getKeySpec(otherKp.getPrivate(), XECPrivateKeySpec.class);
 460         try {
 461             kf.generatePrivate(otherPriSpec);
 462             throw new RuntimeException(name + " KeyFactory accepted "
 463                 + param.toString() + " key");
 464         } catch (InvalidKeySpecException ex) {
 465             // expected
 466         }
 467 
 468         // ensure the KeyAgreement rejects incorrect keys
 469         KeyAgreement ka = KeyAgreement.getInstance(name, providerName);
 470         try {
 471             ka.init(otherKp.getPrivate());
 472             throw new RuntimeException(name + " KeyAgreement accepted "
 473                 + param.toString() + " key");
 474         } catch (InvalidKeyException ex) {
 475             // expected
 476         }
 477         KeyPair kp = kpg.generateKeyPair();
 478         ka.init(kp.getPrivate());
 479         try {
 480             // This should always be rejected because it doesn't match the key
 481             // passed to init, but it is tested here for good measure.
 482             ka.doPhase(otherKp.getPublic(), true);
 483             throw new RuntimeException(name + " KeyAgreement accepted "
 484                 + param.toString() + " key");
 485         } catch (InvalidKeyException ex) {
 486             // expected
 487         }
 488     }
 489 }
 490