• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package test.java.security.KeyAgreement;
35 
36 import java.security.KeyPair;
37 import java.security.KeyPairGenerator;
38 import java.util.Arrays;
39 import java.util.concurrent.CountDownLatch;
40 import java.util.concurrent.ExecutorService;
41 import java.util.concurrent.Executors;
42 import java.util.concurrent.ThreadFactory;
43 import javax.crypto.KeyAgreement;
44 import org.testng.annotations.Test;
45 import static org.junit.Assert.fail;
46 
47 /**
48  * This test targets KeyPairGenerator API related issue in a multi threaded
49  * context.
50  */
51 public class MultiThreadTest {
52 
53     // Tested a shared KeyPairGenerator with 100 number of threads.
54     private static final int THREAD_COUNT = 100;
55 
56     @Test
testDHKeySpecs()57     public void testDHKeySpecs() throws Exception {
58         KeyPairGenerator kpg = genKeyGenerator("BC","DiffieHellman",
59                 "DiffieHellman");
60         new MultiThreadTest().runTest("BC", "DiffieHellman", kpg);
61     }
62 
63     @Test
testECDHKeySpecs()64     public void testECDHKeySpecs() throws Exception {
65         KeyPairGenerator kpg = genKeyGenerator("AndroidOpenSSL","EC",
66                 "EC");
67         new MultiThreadTest().runTest("AndroidOpenSSL", "ECDH", kpg);
68     }
69 
70 
71     // BEGIN Android-removed: XDH is not yet supported
72     /*
73     @Test
74     public void testXDHKeySpecs() throws Exception {
75         KeyPairGenerator kpg1 = genKeyGenerator("AndroidOpenSSL","XDH",
76                 "X25519");
77         new MultiThreadTest().runTest("AndroidOpenSSL", "XDH", kpg1);
78         KeyPairGenerator kpg2 = genKeyGenerator("AndroidOpenSSL","XDH",
79                 "X25519");
80         new MultiThreadTest().runTest("AndroidOpenSSL", "XDH", kpg2);
81     }
82      */
83     // END Android-removed: XDH is not yet supported
84 
85     /**
86      * Initialize KeyPairGenerator based on different algorithm names.
87      */
genKeyGenerator(String provider, String kpgAlgo, String kpgInit)88     private static KeyPairGenerator genKeyGenerator(String provider,
89             String kpgAlgo, String kpgInit) throws Exception {
90 
91         KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
92         switch (kpgInit) {
93             case "DiffieHellman":
94                 kpg.initialize(512);
95                 break;
96             case "EC":
97                 kpg.initialize(256);
98                 break;
99             case "X25519":
100                 kpg.initialize(255);
101                 break;
102             case "X448":
103                 kpg.initialize(448);
104                 break;
105             default:
106                 fail("Invalid Algo name " + kpgInit);
107         }
108         return kpg;
109     }
110 
runTest(String provider, String kaAlgo, KeyPairGenerator kpg)111     private void runTest(String provider, String kaAlgo, KeyPairGenerator kpg)
112             throws Exception {
113 
114         ExecutorService executor = null;
115         try {
116             executor = Executors.newCachedThreadPool(new ThreadFactory() {
117                 @Override
118                 public Thread newThread(Runnable r) {
119                     Thread t = Executors.defaultThreadFactory().newThread(r);
120                     t.setDaemon(true);
121                     return t;
122                 }
123             });
124             CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
125 
126             for (int i = 0; i < THREAD_COUNT; i++) {
127                 executor.execute(new Runnable() {
128                     @Override
129                     public void run() {
130                         try {
131                             testKeyAgreement(provider, kaAlgo, kpg);
132                         } catch (Exception e) {
133                             throw new RuntimeException(e);
134                         } finally {
135                             // Indicate a task completed.
136                             latch.countDown();
137                         }
138                     }
139                 });
140             }
141             // Wait till all tasks get complete.
142             latch.await();
143         } finally {
144             if (executor != null) {
145                 executor.shutdown();
146             }
147         }
148     }
149 
150     /**
151      * Perform KeyAgreement operation with a shared KeyPairGenerator instance.
152      */
testKeyAgreement(String provider, String kaAlgo, KeyPairGenerator kpg)153     private static void testKeyAgreement(String provider, String kaAlgo,
154             KeyPairGenerator kpg) throws Exception {
155 
156         KeyPair kp1 = kpg.generateKeyPair();
157         KeyPair kp2 = kpg.generateKeyPair();
158 
159         KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo, provider);
160         ka1.init(kp1.getPrivate());
161         ka1.doPhase(kp2.getPublic(), true);
162         byte[] secret1 = ka1.generateSecret();
163         KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider);
164         ka2.init(kp2.getPrivate());
165         ka2.doPhase(kp1.getPublic(), true);
166         byte[] secret2 = ka2.generateSecret();
167 
168         // With related keypairs, generated KeyAgreement secret should be same.
169         if (!Arrays.equals(secret1, secret2)) {
170             fail("KeyAgreement secret mismatch.");
171         }
172     }
173 }