1 /*
2  * Copyright (c) 2005, 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.  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.mscapi;
27 
28 import java.util.UUID;
29 import java.security.*;
30 import java.security.spec.AlgorithmParameterSpec;
31 import java.security.spec.RSAKeyGenParameterSpec;
32 
33 import sun.security.rsa.RSAKeyFactory;
34 import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE;
35 
36 /**
37  * RSA keypair generator.
38  *
39  * Standard algorithm, minimum key length is 512 bit, maximum is 16,384.
40  * Generates a private key that is exportable.
41  *
42  * @since 1.6
43  */
44 public abstract class CKeyPairGenerator extends KeyPairGeneratorSpi {
45 
46     protected String keyAlg;
47 
CKeyPairGenerator(String keyAlg)48     public CKeyPairGenerator(String keyAlg) {
49         this.keyAlg = keyAlg;
50     }
51 
52     public static class RSA extends CKeyPairGenerator {
RSA()53         public RSA() {
54             super("RSA");
55             // initialize to default in case the app does not call initialize()
56             initialize(DEF_RSA_KEY_SIZE, null);
57         }
58 
59         // Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers
60         static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
61         static final int KEY_SIZE_MAX = 16384;
62 
63         // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
64         private int keySize;
65 
66         // initialize the generator. See JCA doc
67         // random is always ignored
68         @Override
initialize(int keySize, SecureRandom random)69         public void initialize(int keySize, SecureRandom random) {
70 
71             try {
72                 RSAKeyFactory.checkKeyLengths(keySize, null,
73                         KEY_SIZE_MIN, KEY_SIZE_MAX);
74             } catch (InvalidKeyException e) {
75                 throw new InvalidParameterException(e.getMessage());
76             }
77 
78             this.keySize = keySize;
79         }
80 
81         // second initialize method. See JCA doc
82         // random and exponent are always ignored
83         @Override
initialize(AlgorithmParameterSpec params, SecureRandom random)84         public void initialize(AlgorithmParameterSpec params, SecureRandom random)
85                 throws InvalidAlgorithmParameterException {
86 
87             int tmpSize;
88             if (params == null) {
89                 tmpSize = DEF_RSA_KEY_SIZE;
90             } else if (params instanceof RSAKeyGenParameterSpec) {
91 
92                 if (((RSAKeyGenParameterSpec) params).getPublicExponent() != null) {
93                     throw new InvalidAlgorithmParameterException
94                             ("Exponent parameter is not supported");
95                 }
96                 tmpSize = ((RSAKeyGenParameterSpec) params).getKeysize();
97 
98             } else {
99                 throw new InvalidAlgorithmParameterException
100                         ("Params must be an instance of RSAKeyGenParameterSpec");
101             }
102 
103             try {
104                 RSAKeyFactory.checkKeyLengths(tmpSize, null,
105                         KEY_SIZE_MIN, KEY_SIZE_MAX);
106             } catch (InvalidKeyException e) {
107                 throw new InvalidAlgorithmParameterException(
108                         "Invalid Key sizes", e);
109             }
110 
111             this.keySize = tmpSize;
112         }
113 
114         // generate the keypair. See JCA doc
115         @Override
generateKeyPair()116         public KeyPair generateKeyPair() {
117 
118             try {
119                 // Generate each keypair in a unique key container
120                 CKeyPair keys =
121                         generateCKeyPair(keyAlg, keySize,
122                                 "{" + UUID.randomUUID().toString() + "}");
123                 return new KeyPair(keys.getPublic(), keys.getPrivate());
124 
125             } catch (KeyException e) {
126                 throw new ProviderException(e);
127             }
128         }
129 
generateCKeyPair(String alg, int keySize, String keyContainerName)130         private static native CKeyPair generateCKeyPair(String alg, int keySize,
131                 String keyContainerName) throws KeyException;
132     }
133 }
134