]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/frontends/android/app/src/main/java/org/strongswan/android/security/LocalCertificateStore.java
android: Migrate to the Gradle build system
[thirdparty/strongswan.git] / src / frontends / android / app / src / main / java / org / strongswan / android / security / LocalCertificateStore.java
1 /*
2 * Copyright (C) 2014 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 package org.strongswan.android.security;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.security.MessageDigest;
24 import java.security.NoSuchAlgorithmException;
25 import java.security.cert.Certificate;
26 import java.security.cert.CertificateEncodingException;
27 import java.security.cert.CertificateException;
28 import java.security.cert.CertificateFactory;
29 import java.security.cert.X509Certificate;
30 import java.util.ArrayList;
31 import java.util.Date;
32 import java.util.regex.Pattern;
33
34 import org.strongswan.android.logic.StrongSwanApplication;
35 import org.strongswan.android.utils.Utils;
36
37 import android.content.Context;
38
39 public class LocalCertificateStore
40 {
41 private static final String FILE_PREFIX = "certificate-";
42 private static final String ALIAS_PREFIX = "local:";
43 private static final Pattern ALIAS_PATTERN = Pattern.compile("^" + ALIAS_PREFIX + "[0-9a-f]{40}$");
44
45 /**
46 * Add the given certificate to the store
47 * @param cert the certificate to add
48 * @return true if successful
49 */
50 public boolean addCertificate(Certificate cert)
51 {
52 if (!(cert instanceof X509Certificate))
53 { /* only accept X.509 certificates */
54 return false;
55 }
56 String keyid = getKeyId(cert);
57 if (keyid == null)
58 {
59 return false;
60 }
61 FileOutputStream out;
62 try
63 {
64 /* we replace any existing file with the same alias */
65 out = StrongSwanApplication.getContext().openFileOutput(FILE_PREFIX + keyid, Context.MODE_PRIVATE);
66 try
67 {
68 out.write(cert.getEncoded());
69 return true;
70 }
71 catch (CertificateEncodingException e)
72 {
73 e.printStackTrace();
74 }
75 catch (IOException e)
76 {
77 e.printStackTrace();
78 }
79 finally
80 {
81 try
82 {
83 out.close();
84 }
85 catch (IOException e)
86 {
87 e.printStackTrace();
88 }
89 }
90 }
91 catch (FileNotFoundException e)
92 {
93 e.printStackTrace();
94 }
95 return false;
96 }
97
98 /**
99 * Delete the certificate with the given alias
100 * @param alias a certificate's alias
101 */
102 public void deleteCertificate(String alias)
103 {
104 if (ALIAS_PATTERN.matcher(alias).matches())
105 {
106 alias = alias.substring(ALIAS_PREFIX.length());
107 StrongSwanApplication.getContext().deleteFile(FILE_PREFIX + alias);
108 }
109 }
110
111 /**
112 * Retrieve the certificate with the given alias
113 * @param alias a certificate's alias
114 * @return certificate object or null
115 */
116 public X509Certificate getCertificate(String alias)
117 {
118 if (!ALIAS_PATTERN.matcher(alias).matches())
119 {
120 return null;
121 }
122 alias = alias.substring(ALIAS_PREFIX.length());
123 try
124 {
125 FileInputStream in = StrongSwanApplication.getContext().openFileInput(FILE_PREFIX + alias);
126 try
127 {
128 CertificateFactory factory = CertificateFactory.getInstance("X.509");
129 X509Certificate certificate = (X509Certificate)factory.generateCertificate(in);
130 return certificate;
131 }
132 catch (CertificateException e)
133 {
134 e.printStackTrace();
135 }
136 finally
137 {
138 try
139 {
140 in.close();
141 }
142 catch (IOException e)
143 {
144 e.printStackTrace();
145 }
146 }
147 }
148 catch (FileNotFoundException e)
149 {
150 e.printStackTrace();
151 }
152 return null;
153 }
154
155 /**
156 * Returns the creation date of the certificate with the given alias
157 * @param alias certificate alias
158 * @return creation date or null if not found
159 */
160 public Date getCreationDate(String alias)
161 {
162 if (!ALIAS_PATTERN.matcher(alias).matches())
163 {
164 return null;
165 }
166 alias = alias.substring(ALIAS_PREFIX.length());
167 File file = StrongSwanApplication.getContext().getFileStreamPath(FILE_PREFIX + alias);
168 return file.exists() ? new Date(file.lastModified()) : null;
169 }
170
171 /**
172 * Returns a list of all known certificate aliases
173 * @return list of aliases
174 */
175 public ArrayList<String> aliases()
176 {
177 ArrayList<String> list = new ArrayList<String>();
178 for (String file : StrongSwanApplication.getContext().fileList())
179 {
180 if (file.startsWith(FILE_PREFIX))
181 {
182 list.add(ALIAS_PREFIX + file.substring(FILE_PREFIX.length()));
183 }
184 }
185 return list;
186 }
187
188 /**
189 * Check if the store contains a certificate with the given alias
190 * @param alias certificate alias
191 * @return true if the store contains the certificate
192 */
193 public boolean containsAlias(String alias)
194 {
195 return getCreationDate(alias) != null;
196 }
197
198 /**
199 * Returns a certificate alias based on a SHA-1 hash of the public key.
200 *
201 * @param cert certificate to get an alias for
202 * @return hex encoded alias, or null if failed
203 */
204 public String getCertificateAlias(Certificate cert)
205 {
206 String keyid = getKeyId(cert);
207 return keyid != null ? ALIAS_PREFIX + keyid : null;
208 }
209
210 /**
211 * Calculates the SHA-1 hash of the public key of the given certificate.
212 * @param cert certificate to get the key ID from
213 * @return hex encoded SHA-1 hash of the public key or null if failed
214 */
215 private String getKeyId(Certificate cert)
216 {
217 MessageDigest md;
218 try
219 {
220 md = java.security.MessageDigest.getInstance("SHA1");
221 byte[] hash = md.digest(cert.getPublicKey().getEncoded());
222 return Utils.bytesToHex(hash);
223 }
224 catch (NoSuchAlgorithmException e)
225 {
226 e.printStackTrace();
227 }
228 return null;
229 }
230 }