1 /*
2  * Copyright (c) 2018, 2021, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.security.ec;
27 
28 import java.math.BigInteger;
29 import java.security.KeyPairGeneratorSpi;
30 import java.security.InvalidKeyException;
31 import java.security.InvalidParameterException;
32 import java.security.InvalidAlgorithmParameterException;
33 import java.security.KeyPair;
34 import java.security.ProviderException;
35 import java.security.SecureRandom;
36 import java.security.spec.AlgorithmParameterSpec;
37 import java.security.spec.NamedParameterSpec;
38 import java.util.Arrays;
39 
40 import sun.security.jca.JCAUtil;
41 
42 /**
43  * Key pair generator for the XDH key agreement algorithm.
44  */
45 public class XDHKeyPairGenerator extends KeyPairGeneratorSpi {
46 
47     private static final NamedParameterSpec DEFAULT_PARAM_SPEC
48         = NamedParameterSpec.X25519;
49 
50     private SecureRandom random = null;
51     private XECOperations ops = null;
52     private XECParameters lockedParams = null;
53 
XDHKeyPairGenerator()54     XDHKeyPairGenerator() {
55         tryInitialize(DEFAULT_PARAM_SPEC);
56     }
57 
XDHKeyPairGenerator(NamedParameterSpec paramSpec)58     private XDHKeyPairGenerator(NamedParameterSpec paramSpec) {
59         tryInitialize(paramSpec);
60         lockedParams = ops.getParameters();
61     }
62 
tryInitialize(NamedParameterSpec paramSpec)63     private void tryInitialize(NamedParameterSpec paramSpec) {
64         try {
65             initialize(paramSpec, null);
66         } catch (InvalidAlgorithmParameterException ex) {
67             String name = paramSpec.getName();
68             throw new ProviderException(name + " not supported");
69         }
70     }
71 
72     @Override
initialize(int keySize, SecureRandom random)73     public void initialize(int keySize, SecureRandom random) {
74 
75         XECParameters params = XECParameters.getBySize(
76             InvalidParameterException::new, keySize);
77 
78         initializeImpl(params, random);
79     }
80 
81     @Override
initialize(AlgorithmParameterSpec params, SecureRandom random)82     public void initialize(AlgorithmParameterSpec params, SecureRandom random)
83             throws InvalidAlgorithmParameterException {
84 
85         XECParameters xecParams = XECParameters.get(
86             InvalidAlgorithmParameterException::new, params);
87 
88         initializeImpl(xecParams, random);
89     }
90 
initializeImpl(XECParameters params, SecureRandom random)91     private void initializeImpl(XECParameters params, SecureRandom random) {
92 
93         if (lockedParams != null && lockedParams != params) {
94             throw new InvalidParameterException("Parameters must be " +
95                 lockedParams.getName());
96         }
97 
98         this.ops = new XECOperations(params);
99         this.random = random == null ? JCAUtil.getSecureRandom() : random;
100     }
101 
102 
103     @Override
generateKeyPair()104     public KeyPair generateKeyPair() {
105 
106         byte[] privateKey = ops.generatePrivate(random);
107         // computePublic may modify the private key, so clone it first
108         byte[] cloned = privateKey.clone();
109         BigInteger publicKey = ops.computePublic(cloned);
110         Arrays.fill(cloned, (byte)0);
111 
112         try {
113             return new KeyPair(
114                 new XDHPublicKeyImpl(ops.getParameters(), publicKey),
115                 new XDHPrivateKeyImpl(ops.getParameters(), privateKey)
116             );
117         } catch (InvalidKeyException ex) {
118             throw new ProviderException(ex);
119         } finally {
120             Arrays.fill(privateKey, (byte)0);
121         }
122     }
123 
124     static class X25519 extends XDHKeyPairGenerator {
125 
X25519()126         public X25519() {
127             super(NamedParameterSpec.X25519);
128         }
129     }
130 
131     static class X448 extends XDHKeyPairGenerator {
132 
X448()133         public X448() {
134             super(NamedParameterSpec.X448);
135         }
136     }
137 }
138