Updating Nokia driver
[vfc/nfvo/driver/vnfm/svnfm.git] / nokiav2 / driver / src / main / java / org / onap / vfc / nfvo / driver / vnfm / svnfm / nokia / util / StoreLoader.java
1 /*
2  * Copyright 2016-2017, Nokia Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util;
18
19 import org.apache.commons.codec.binary.Base64;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.InputStream;
23 import java.security.KeyFactory;
24 import java.security.KeyStore;
25 import java.security.KeyStore.TrustedCertificateEntry;
26 import java.security.NoSuchAlgorithmException;
27 import java.security.PrivateKey;
28 import java.security.cert.Certificate;
29 import java.security.cert.CertificateFactory;
30 import java.security.spec.InvalidKeySpecException;
31 import java.security.spec.PKCS8EncodedKeySpec;
32 import java.util.Collection;
33 import java.util.HashSet;
34 import java.util.Optional;
35 import java.util.Set;
36
37 import static org.slf4j.LoggerFactory.getLogger;
38
39 /**
40  * Create Truststore from the given certificates and keys
41  */
42 public final class StoreLoader {
43
44     public static final String PASSWORD = "password";
45     private static final String RSA = "RSA";
46     private static final String X_509 = "X.509";
47     private static final String SUN = "SUN";
48     private static final String JKS = "JKS";
49     private static final String RSA_PRIVATE_KEY = "RSA PRIVATE KEY";
50     private static final String CERTIFICATE = "CERTIFICATE";
51     private static org.slf4j.Logger logger = getLogger(StoreLoader.class);
52
53     private StoreLoader() {
54     }
55
56     private static String getScope(String content, String scope) {
57         int rindex = content.indexOf(begin(scope));
58         int lindex = content.indexOf(end(scope));
59         if (rindex == -1 || lindex == -1) {
60             return "";
61         }
62         String substring = content.substring(rindex, lindex) + end(scope);
63         return substring;
64     }
65
66     /**
67      * @param content the content of the PEM ( a PEM may contain multiple certificates)
68      * @return the collection of certificates in the PEM
69      */
70     public static Set<String> getCertifacates(String content) {
71         String lastCertificate = "";
72         Set<String> certificates = new HashSet<>();
73         do {
74             lastCertificate = getScope(content, CERTIFICATE);
75             content = content.replace(lastCertificate, "");
76             if (!"".equals(lastCertificate)) {
77                 certificates.add(lastCertificate);
78             }
79         } while (!"".equals(lastCertificate));
80         return certificates;
81     }
82
83     private static byte[] toDer(String pem, String scope) {
84         return Base64.decodeBase64(pem
85                 .replace(begin(scope), "")
86                 .replace(end(scope), "")
87                 .replaceAll("\\s", ""));
88     }
89
90     private static String begin(String scope) {
91         return "-----BEGIN " + scope + "-----";
92     }
93
94     private static String end(String scope) {
95         return "-----END " + scope + "-----";
96     }
97
98     /**
99      * Create new truststore from the given certificate
100      *
101      * @param pem           the certificate which used to create the store
102      * @param storePassword the password to protect the store
103      * @param keyPassword   the password to protect the key
104      * @return the created key store
105      */
106     public static KeyStore loadStore(String pem, String storePassword, String keyPassword) {
107         Optional<PrivateKey> privateKey = generatePrivateKey(pem);
108         Certificate[] certs = createCertificates(pem);
109         try {
110             KeyStore ks = KeyStore.getInstance(JKS, SUN);
111             ks.load(null, storePassword.toCharArray());
112             if (privateKey.isPresent()) {
113                 ks.setKeyEntry(PASSWORD, privateKey.get(), keyPassword.toCharArray(), certs);
114             } else if (certs != null) {
115                 int index = 0;
116                 for (Certificate cert : certs) {
117                     TrustedCertificateEntry ts = new TrustedCertificateEntry(cert);
118                     ks.setEntry(PASSWORD + index, ts, null);
119                     index++;
120                 }
121             }
122             return ks;
123         } catch (Exception e) {
124             throw new RuntimeException("Unable to create keystore", e);
125         }
126     }
127
128     private static Certificate[] createCertificates(String pem) {
129         Set<Certificate> certificates = new HashSet<>();
130         try {
131             for (String certificate : getCertifacates(pem)) {
132                 CertificateFactory certFactory = CertificateFactory.getInstance(X_509);
133
134                 InputStream is = new ByteArrayInputStream(toDer(certificate, CERTIFICATE));
135                 Collection<? extends Certificate> c = certFactory.generateCertificates(is);
136                 certificates.addAll(c);
137             }
138         } catch (Exception e) {
139             logger.error(e.getMessage(), e);
140             throw new RuntimeException("Unable to load certificates", e);
141         }
142
143         if (certificates.size() > 0) {
144             return certificates.toArray(new Certificate[certificates.size()]);
145         } else {
146             return null;
147         }
148     }
149
150     private static Optional<PrivateKey> generatePrivateKey(String pem) {
151         try {
152             String key = getScope(pem, RSA_PRIVATE_KEY);
153             if (!key.isEmpty()) {
154                 KeyFactory keyFactory = KeyFactory.getInstance(RSA);
155                 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(toDer(key, RSA_PRIVATE_KEY));
156                 return Optional.of(keyFactory.generatePrivate(keySpec));
157             }
158             return Optional.empty();
159         } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
160             logger.error("Unable to load key", e);
161             throw new RuntimeException("Unable to load key", e);
162         }
163     }
164
165 }