blob: 5ea288f3ca9f57ffa09c29a0bce7ad0c37dccb65 [file] [log] [blame]
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
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
17package org.apache.harmony.xnet.provider.jsse;
18
Brian Carlstrom12cd1f02010-06-22 23:43:20 -070019import java.util.HashMap;
20import java.util.Map;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080021import java.security.InvalidKeyException;
22import java.security.InvalidParameterException;
23import java.security.NoSuchAlgorithmException;
24import java.security.PrivateKey;
25import java.security.PublicKey;
26import java.security.Signature;
27import java.security.SignatureException;
28import java.security.interfaces.DSAParams;
29import java.security.interfaces.DSAPublicKey;
30import java.security.interfaces.RSAPublicKey;
31
32/**
Brian Carlstrom12cd1f02010-06-22 23:43:20 -070033 * Implements the subset of the JDK Signature interface needed for
34 * signature verification using OpenSSL.
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080035 */
36public class OpenSSLSignature extends Signature {
37
Brian Carlstrom12cd1f02010-06-22 23:43:20 -070038 private static Map<String,Class<? extends OpenSSLSignature>> jdkToOpenSsl
39 = new HashMap<String,Class<? extends OpenSSLSignature>>();
40
41 static {
42 // TODO Finish OpenSSLSignature implementation and move
43 // registration information to the OpenSSLProvider
44 jdkToOpenSsl.put("MD5WithRSAEncryption", MD5RSA.class);
45 jdkToOpenSsl.put("MD5WithRSA", MD5RSA.class);
46 jdkToOpenSsl.put("MD5/RSA", MD5RSA.class);
47 jdkToOpenSsl.put("1.2.840.113549.1.1.4", MD5RSA.class);
48 jdkToOpenSsl.put("1.2.840.113549.2.5with1.2.840.113549.1.1.1", MD5RSA.class);
49
50 jdkToOpenSsl.put("SHA1WithRSAEncryption", SHA1RSA.class);
51 jdkToOpenSsl.put("SHA1WithRSA", SHA1RSA.class);
52 jdkToOpenSsl.put("SHA1/RSA", SHA1RSA.class);
53 jdkToOpenSsl.put("SHA-1/RSA", SHA1RSA.class);
54 jdkToOpenSsl.put("1.2.840.113549.1.1.5", SHA1RSA.class);
55 jdkToOpenSsl.put("1.3.14.3.2.26with1.2.840.113549.1.1.1", SHA1RSA.class);
56 jdkToOpenSsl.put("1.3.14.3.2.26with1.2.840.113549.1.1.5", SHA1RSA.class);
57 jdkToOpenSsl.put("1.3.14.3.2.29", SHA1RSA.class);
58
59 jdkToOpenSsl.put("SHA256WithRSAEncryption", SHA256RSA.class);
60 jdkToOpenSsl.put("SHA256WithRSA", SHA256RSA.class);
61 jdkToOpenSsl.put("1.2.840.113549.1.1.11", SHA256RSA.class);
62
63 jdkToOpenSsl.put("SHA384WithRSAEncryption", SHA384RSA.class);
64 jdkToOpenSsl.put("SHA384WithRSA", SHA384RSA.class);
65 jdkToOpenSsl.put("1.2.840.113549.1.1.12", SHA384RSA.class);
66
67 jdkToOpenSsl.put("SHA512WithRSAEncryption", SHA512RSA.class);
68 jdkToOpenSsl.put("SHA512WithRSA", SHA512RSA.class);
69 jdkToOpenSsl.put("1.2.840.113549.1.1.13", SHA512RSA.class);
70
71 jdkToOpenSsl.put("SHA1withDSA", SHA1DSA.class);
72 jdkToOpenSsl.put("SHA/DSA", SHA1DSA.class);
73 jdkToOpenSsl.put("DSA", SHA1DSA.class);
74 jdkToOpenSsl.put("1.3.14.3.2.26with1.2.840.10040.4.1", SHA1DSA.class);
75 jdkToOpenSsl.put("1.3.14.3.2.26with1.2.840.10040.4.3", SHA1DSA.class);
76 jdkToOpenSsl.put("DSAWithSHA1", SHA1DSA.class);
77 jdkToOpenSsl.put("1.2.840.10040.4.3", SHA1DSA.class);
78 }
79
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080080 /**
81 * Holds a pointer to the native message digest context.
82 */
Brian Carlstrom12cd1f02010-06-22 23:43:20 -070083 private final int ctx;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080084
85 /**
86 * Holds a pointer to the native DSA key.
87 */
88 private int dsa;
89
90 /**
91 * Holds a pointer to the native RSA key.
92 */
93 private int rsa;
Elliott Hughesf33eae72010-05-13 12:36:25 -070094
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080095 /**
Elliott Hughesf33eae72010-05-13 12:36:25 -070096 * Holds the OpenSSL name of the algorithm (lower case, no dashes).
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080097 */
Brian Carlstrom12cd1f02010-06-22 23:43:20 -070098 private final String evpAlgorithm;
Elliott Hughesf33eae72010-05-13 12:36:25 -070099
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800100 /**
101 * Holds a dummy buffer for writing single bytes to the digest.
102 */
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700103 private final byte[] singleByte = new byte[1];
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800104
105 /**
106 * Creates a new OpenSSLSignature instance for the given algorithm name.
Elliott Hughesf33eae72010-05-13 12:36:25 -0700107 *
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700108 * @param algorithm The name of the algorithm, e.g. "SHA1WithRSA".
Elliott Hughesf33eae72010-05-13 12:36:25 -0700109 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800110 * @return The new OpenSSLSignature instance.
Elliott Hughesf33eae72010-05-13 12:36:25 -0700111 *
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800112 * @throws RuntimeException In case of problems.
113 */
114 public static OpenSSLSignature getInstance(String algorithm) throws NoSuchAlgorithmException {
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700115 // System.out.println("getInstance() invoked with " + algorithm);
116
117 Class <? extends OpenSSLSignature> clazz = jdkToOpenSsl.get(algorithm);
118 if (clazz == null) {
119 throw new NoSuchAlgorithmException(algorithm);
120 }
121 try {
122 return clazz.newInstance();
123 } catch (InstantiationException e) {
124 throw new NoSuchAlgorithmException(algorithm, e);
125 } catch (IllegalAccessException e) {
126 throw new NoSuchAlgorithmException(algorithm, e);
127 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800128 }
129
130 /**
131 * Creates a new OpenSSLSignature instance for the given algorithm name.
Elliott Hughesf33eae72010-05-13 12:36:25 -0700132 *
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700133 * @param algorithm OpenSSL name of the algorithm, e.g. "RSA-SHA1".
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800134 */
135 private OpenSSLSignature(String algorithm) throws NoSuchAlgorithmException {
136 super(algorithm);
Elliott Hughesf33eae72010-05-13 12:36:25 -0700137
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700138 // We don't support MD2
139 if ("RSA-MD2".equals(algorithm)) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800140 throw new NoSuchAlgorithmException(algorithm);
141 }
142
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700143 this.evpAlgorithm = algorithm;
144 this.ctx = NativeCrypto.EVP_new();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800145 }
Elliott Hughesf33eae72010-05-13 12:36:25 -0700146
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800147 @Override
148 protected void engineUpdate(byte input) {
149 singleByte[0] = input;
150 engineUpdate(singleByte, 0, 1);
151 }
152
153 @Override
154 protected void engineUpdate(byte[] input, int offset, int len) {
155 if (state == SIGN) {
156 throw new UnsupportedOperationException();
157 } else {
158 NativeCrypto.EVP_VerifyUpdate(ctx, input, offset, len);
159 }
160 }
161
162 @Override
163 protected Object engineGetParameter(String param) throws InvalidParameterException {
164 return null;
165 }
166
167 @Override
168 protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
169 throw new UnsupportedOperationException();
170 }
171
172 @Override
173 protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700174 // System.out.println("engineInitVerify() invoked with "
175 // + publicKey.getClass().getCanonicalName());
Elliott Hughesf33eae72010-05-13 12:36:25 -0700176
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800177 if (publicKey instanceof DSAPublicKey) {
178 try {
179 DSAPublicKey dsaPublicKey = (DSAPublicKey)publicKey;
180 DSAParams dsaParams = dsaPublicKey.getParams();
Elliott Hughesf33eae72010-05-13 12:36:25 -0700181 dsa = NativeCrypto.EVP_PKEY_new_DSA(dsaParams.getP().toByteArray(),
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800182 dsaParams.getQ().toByteArray(), dsaParams.getG().toByteArray(),
183 dsaPublicKey.getY().toByteArray(), null);
184
185 } catch (Exception ex) {
186 throw new InvalidKeyException(ex.toString());
187 }
188 } else if (publicKey instanceof RSAPublicKey) {
189 try {
190 RSAPublicKey rsaPublicKey = (RSAPublicKey)publicKey;
191 rsa = NativeCrypto.EVP_PKEY_new_RSA(rsaPublicKey.getModulus().toByteArray(),
192 rsaPublicKey.getPublicExponent().toByteArray(), null, null, null);
193
194 } catch (Exception ex) {
195 throw new InvalidKeyException(ex.toString());
196 }
197 } else {
198 throw new InvalidKeyException("Need DSA or RSA public key");
199 }
Elliott Hughesf33eae72010-05-13 12:36:25 -0700200
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800201 try {
202 NativeCrypto.EVP_VerifyInit(ctx, evpAlgorithm);
203 } catch (Exception ex) {
204 throw new RuntimeException(ex);
205 }
206 }
207
208 @Override
209 protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
210 }
211
212 @Override
213 protected byte[] engineSign() throws SignatureException {
214 throw new UnsupportedOperationException();
215 }
216
217 @Override
218 protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
219 int handle = (rsa != 0) ? rsa : dsa;
Elliott Hughesf33eae72010-05-13 12:36:25 -0700220
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800221 if (handle == 0) {
222 // This can't actually happen, but you never know...
223 throw new SignatureException("Need DSA or RSA public key");
224 }
Elliott Hughesf33eae72010-05-13 12:36:25 -0700225
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800226 try {
227 int result = NativeCrypto.EVP_VerifyFinal(ctx, sigBytes, 0, sigBytes.length, handle);
228 return result == 1;
229 } catch (Exception ex) {
230 throw new SignatureException(ex);
231 }
Elliott Hughesf33eae72010-05-13 12:36:25 -0700232
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800233 }
234
235 @Override
236 protected void finalize() throws Throwable {
237 super.finalize();
Elliott Hughesf33eae72010-05-13 12:36:25 -0700238
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800239 if (dsa != 0) {
240 NativeCrypto.EVP_PKEY_free(dsa);
241 }
242
243 if (rsa != 0) {
244 NativeCrypto.EVP_PKEY_free(rsa);
245 }
Elliott Hughesf33eae72010-05-13 12:36:25 -0700246
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800247 if (ctx != 0) {
248 NativeCrypto.EVP_free(ctx);
249 }
250 }
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700251
252 public static final class MD5RSA extends OpenSSLSignature {
253 public MD5RSA() throws NoSuchAlgorithmException {
254 super("RSA-MD5");
255 }
256 }
257 public static final class SHA1RSA extends OpenSSLSignature {
258 public SHA1RSA() throws NoSuchAlgorithmException {
259 super("RSA-SHA1");
260 }
261 }
262 public static final class SHA256RSA extends OpenSSLSignature {
263 public SHA256RSA() throws NoSuchAlgorithmException {
264 super("RSA-SHA256");
265 }
266 }
267 public static final class SHA384RSA extends OpenSSLSignature {
268 public SHA384RSA() throws NoSuchAlgorithmException {
269 super("RSA-SHA384");
270 }
271 }
272 public static final class SHA512RSA extends OpenSSLSignature {
273 public SHA512RSA() throws NoSuchAlgorithmException {
274 super("RSA-SHA512");
275 }
276 }
277 public static final class SHA1DSA extends OpenSSLSignature {
278 public SHA1DSA() throws NoSuchAlgorithmException {
279 super("DSA-SHA1");
280 }
281 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800282}
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700283