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 8184359
27  * @summary KeyPairGenerator Test with multiple threads.
28  *  Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <Curve*>
29  * @run main MultiThreadTest DiffieHellman SunJCE DiffieHellman
30  * @run main MultiThreadTest ECDH SunEC EC
31  * @run main MultiThreadTest XDH SunEC XDH X25519
32  * @run main MultiThreadTest XDH SunEC XDH X448
33  */
34 import java.security.KeyPair;
35 import java.security.KeyPairGenerator;
36 import java.util.Arrays;
37 import java.util.concurrent.CountDownLatch;
38 import java.util.concurrent.ExecutorService;
39 import java.util.concurrent.Executors;
40 import java.util.concurrent.ThreadFactory;
41 import javax.crypto.KeyAgreement;
42 
43 /**
44  * This test targets KeyPairGenerator API related issue in a multi threaded
45  * context.
46  */
47 public class MultiThreadTest {
48 
49     // Tested a shared KeyPairGenerator with 100 number of threads.
50     private static final int THREAD_COUNT = 100;
51 
main(String[] args)52     public static void main(String[] args) throws Exception {
53 
54         String kaAlgo = args[0];
55         String provider = args[1];
56         String kpgAlgo = args[2];
57         KeyPairGenerator kpg = genKeyGenerator(provider, kpgAlgo,
58                 (args.length > 3) ? args[3] : kpgAlgo);
59         new MultiThreadTest().runTest(provider, kaAlgo, kpg);
60     }
61 
62     /**
63      * Initialize KeyPairGenerator based on different algorithm names.
64      */
genKeyGenerator(String provider, String kpgAlgo, String kpgInit)65     private static KeyPairGenerator genKeyGenerator(String provider,
66             String kpgAlgo, String kpgInit) throws Exception {
67 
68         KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
69         switch (kpgInit) {
70             case "DiffieHellman":
71                 kpg.initialize(512);
72                 break;
73             case "EC":
74                 kpg.initialize(256);
75                 break;
76             case "X25519":
77                 kpg.initialize(255);
78                 break;
79             case "X448":
80                 kpg.initialize(448);
81                 break;
82             default:
83                 throw new RuntimeException("Invalid Algo name " + kpgInit);
84         }
85         return kpg;
86     }
87 
runTest(String provider, String kaAlgo, KeyPairGenerator kpg)88     private void runTest(String provider, String kaAlgo, KeyPairGenerator kpg)
89             throws Exception {
90 
91         ExecutorService executor = null;
92         try {
93             executor = Executors.newCachedThreadPool(new ThreadFactory() {
94                 @Override
95                 public Thread newThread(Runnable r) {
96                     Thread t = Executors.defaultThreadFactory().newThread(r);
97                     t.setDaemon(true);
98                     return t;
99                 }
100             });
101             CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
102 
103             for (int i = 0; i < THREAD_COUNT; i++) {
104                 executor.execute(new Runnable() {
105                     @Override
106                     public void run() {
107                         try {
108                             testKeyAgreement(provider, kaAlgo, kpg);
109                         } catch (Exception e) {
110                             throw new RuntimeException(e);
111                         } finally {
112                             // Indicate a task completed.
113                             latch.countDown();
114                         }
115                     }
116                 });
117             }
118             // Wait till all tasks get complete.
119             latch.await();
120         } finally {
121             if (executor != null) {
122                 executor.shutdown();
123             }
124         }
125     }
126 
127     /**
128      * Perform KeyAgreement operation with a shared KeyPairGenerator instance.
129      */
testKeyAgreement(String provider, String kaAlgo, KeyPairGenerator kpg)130     private static void testKeyAgreement(String provider, String kaAlgo,
131             KeyPairGenerator kpg) throws Exception {
132 
133         KeyPair kp1 = kpg.generateKeyPair();
134         KeyPair kp2 = kpg.generateKeyPair();
135 
136         KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo, provider);
137         ka1.init(kp1.getPrivate());
138         ka1.doPhase(kp2.getPublic(), true);
139         byte[] secret1 = ka1.generateSecret();
140         KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider);
141         ka2.init(kp2.getPrivate());
142         ka2.doPhase(kp1.getPublic(), true);
143         byte[] secret2 = ka2.generateSecret();
144 
145         // With related keypairs, generated KeyAgreement secret should be same.
146         if (!Arrays.equals(secret1, secret2)) {
147             throw new Exception("KeyAgreement secret mismatch.");
148         }
149     }
150 }
151