1 /* 2 * Copyright (C) 2012 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 17 package org.apache.harmony.xnet.provider.jsse; 18 19 import java.security.InvalidKeyException; 20 import java.security.NoSuchAlgorithmException; 21 import java.security.PrivateKey; 22 23 import javax.crypto.SecretKey; 24 25 public class OpenSSLEngine { 26 static { 27 NativeCrypto.ENGINE_load_dynamic(); 28 } 29 30 private static final Object mLoadingLock = new Object(); 31 32 /** The ENGINE's native handle. */ 33 private final long ctx; 34 35 public static OpenSSLEngine getInstance(String engine) throws IllegalArgumentException { 36 if (engine == null) { 37 throw new NullPointerException("engine == null"); 38 } 39 40 final long engineCtx; 41 synchronized (mLoadingLock) { 42 engineCtx = NativeCrypto.ENGINE_by_id(engine); 43 if (engineCtx == 0) { 44 throw new IllegalArgumentException("Unknown ENGINE id: " + engine); 45 } 46 47 NativeCrypto.ENGINE_add(engineCtx); 48 } 49 50 return new OpenSSLEngine(engineCtx); 51 } 52 53 private OpenSSLEngine(long engineCtx) { 54 ctx = engineCtx; 55 56 if (NativeCrypto.ENGINE_init(engineCtx) == 0) { 57 NativeCrypto.ENGINE_free(engineCtx); 58 throw new IllegalArgumentException("Could not initialize engine"); 59 } 60 } 61 62 public PrivateKey getPrivateKeyById(String id) throws InvalidKeyException { 63 if (id == null) { 64 throw new NullPointerException("id == null"); 65 } 66 67 final long keyRef = NativeCrypto.ENGINE_load_private_key(ctx, id); 68 if (keyRef == 0) { 69 return null; 70 } 71 72 OpenSSLKey pkey = new OpenSSLKey(keyRef, this, id); 73 try { 74 return pkey.getPrivateKey(); 75 } catch (NoSuchAlgorithmException e) { 76 throw new InvalidKeyException(e); 77 } 78 } 79 80 public SecretKey getSecretKeyById(String id, String algorithm) throws InvalidKeyException { 81 if (id == null) { 82 throw new NullPointerException("id == null"); 83 } 84 85 final long keyRef = NativeCrypto.ENGINE_load_private_key(ctx, id); 86 if (keyRef == 0) { 87 return null; 88 } 89 90 OpenSSLKey pkey = new OpenSSLKey(keyRef, this, id); 91 try { 92 return pkey.getSecretKey(algorithm); 93 } catch (NoSuchAlgorithmException e) { 94 throw new InvalidKeyException(e); 95 } 96 } 97 98 long getEngineContext() { 99 return ctx; 100 } 101 102 @Override 103 protected void finalize() throws Throwable { 104 try { 105 NativeCrypto.ENGINE_finish(ctx); 106 NativeCrypto.ENGINE_free(ctx); 107 } finally { 108 super.finalize(); 109 } 110 } 111 112 @Override 113 public boolean equals(Object o) { 114 if (o == this) { 115 return true; 116 } 117 118 if (!(o instanceof OpenSSLEngine)) { 119 return false; 120 } 121 122 OpenSSLEngine other = (OpenSSLEngine) o; 123 124 if (other.getEngineContext() == ctx) { 125 return true; 126 } 127 128 final String id = NativeCrypto.ENGINE_get_id(ctx); 129 if (id == null) { 130 return false; 131 } 132 133 return id.equals(NativeCrypto.ENGINE_get_id(other.getEngineContext())); 134 } 135 136 @Override 137 public int hashCode() { 138 return (int) ctx; 139 } 140 } 141