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