93635491478be5db10898edceb980eb591a6a604
[iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / resources / credprov / cert / CertificateStorage.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.accountserver.resources.credprov.cert;
23
24 import org.bouncycastle.asn1.x509.BasicConstraints;
25 import org.bouncycastle.asn1.x509.Extension;
26 import org.bouncycastle.jce.ECNamedCurveTable;
27 import org.bouncycastle.operator.OperatorCreationException;
28 import org.iotivity.cloud.accountserver.x509.cert.CertificateBuilder;
29 import org.iotivity.cloud.accountserver.x509.cert.CertificateExtension;
30 import org.iotivity.cloud.util.Log;
31
32 import java.io.FileInputStream;
33 import java.io.FileOutputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.nio.file.Files;
37 import java.nio.file.Paths;
38 import java.security.*;
39 import java.security.cert.Certificate;
40 import java.security.cert.X509Certificate;
41
42 import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*;
43
44 /**
45  * This class is used for loading and storing key store.
46  * Also it generates CA certificate and puts it to keystore.
47  */
48 public final class CertificateStorage {
49
50     /**
51      * This attribute is used to get password to kestore, that stores CA certificate info.
52      * Private key and certificate.
53      */
54     private static final String PASSWORD = PROPERTIES.getProperty("password");
55
56     /**
57      * Root private key is used for signing certificates ans CRLs.
58      */
59     public static PrivateKey ROOT_PRIVATE_KEY;
60
61     /**
62      * Root certificate, is used for isssuing low level certificates.
63      */
64     public static X509Certificate ROOT_CERTIFICATE;
65
66     /**
67      * Keystore object to save, retrieve ca private key and ca certificate from keystore.
68      */
69     private static KeyStore keyStore;
70
71     /**
72      * Private contructor to make this class non-instantiable.
73      */
74     private CertificateStorage() {
75         throw new AssertionError();
76     }
77
78     /**
79      * Loads keystore with null paramaters.
80      * Stores it empty version. Generates CA certificate and private key and
81      * saves it to key storage.
82      */
83     static void init() throws GeneralSecurityException, IOException, OperatorCreationException {
84         Files.createDirectories(Paths.get(KEYSTORE_DIR));
85         keyStore = KeyStore.getInstance(KEYSTORE_TYPE, SECURITY_PROVIDER);
86         keyStore.load(null, null);
87         generate();
88     }
89
90     /**
91      * Loads KeyStore intance from created keystore file and with default password.
92      *
93      * @return KeyStore instance.
94      */
95     static void load() throws GeneralSecurityException, IOException {
96         keyStore = KeyStore.getInstance(KEYSTORE_TYPE, SECURITY_PROVIDER);
97         try (InputStream inputStream = new FileInputStream(KEYSTORE_FILE)) {
98             keyStore.load(inputStream, PASSWORD.toCharArray());
99         } catch (IOException ioException) {
100             Log.e(ioException.getMessage());
101         }
102         ROOT_PRIVATE_KEY = (PrivateKey) keyStore.getKey(CA_ALIAS, PASSWORD.toCharArray());
103         ROOT_CERTIFICATE = (X509Certificate) keyStore.getCertificate(CA_ALIAS);
104     }
105
106     /**
107      * Generates CA X509Certificate and private key and stores it to key storage.
108      *
109      * @return certificate and private key
110      */
111     private static void generate() throws GeneralSecurityException,
112             OperatorCreationException, IOException {
113         if (ROOT_PRIVATE_KEY == null) {
114             KeyPairGenerator g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, SECURITY_PROVIDER);
115             g.initialize(ECNamedCurveTable.getParameterSpec(CURVE), new SecureRandom());
116             KeyPair pair = g.generateKeyPair();
117             ROOT_PRIVATE_KEY = pair.getPrivate();
118             ROOT_CERTIFICATE = new CertificateBuilder(CA_ISSUER, pair.getPublic(),
119                     new CertificateExtension(Extension.basicConstraints, false,
120                             new BasicConstraints(true))).build();
121             keyStore.setCertificateEntry(CA_ALIAS, ROOT_CERTIFICATE);
122             keyStore.setKeyEntry(CA_ALIAS, ROOT_PRIVATE_KEY, PASSWORD.toCharArray(),
123                     new Certificate[]{ROOT_CERTIFICATE});
124             store();
125         }
126     }
127
128     /**
129      * Stores keyStore instance to default keystore file with default password.
130      */
131     private static void store() throws IOException, GeneralSecurityException {
132         try (FileOutputStream out = new FileOutputStream(KEYSTORE_FILE)) {
133             keyStore.store(out, PASSWORD.toCharArray());
134         } catch (IOException ioException) {
135             Log.e(ioException.getMessage());
136         }
137     }
138 }