• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         if (!NativeCrypto.isBoringSSL) {
NativeCrypto.ENGINE_load_dynamic()27             NativeCrypto.ENGINE_load_dynamic();
28         }
29     }
30 
31     private static final Object mLoadingLock = new Object();
32 
33     /** The ENGINE's native handle. */
34     private final long ctx;
35 
36     /**
37      * BoringSSL doesn't really use ENGINE objects, so we just keep this single
38      * instance around to satisfy API calls.
39      */
40     private static class BoringSSL {
41         public static final OpenSSLEngine INSTANCE = new OpenSSLEngine();
42     }
43 
getInstance(String engine)44     public static OpenSSLEngine getInstance(String engine) throws IllegalArgumentException {
45         if (NativeCrypto.isBoringSSL) {
46             return BoringSSL.INSTANCE;
47         }
48 
49         if (engine == null) {
50             throw new NullPointerException("engine == null");
51         }
52 
53         final long engineCtx;
54         synchronized (mLoadingLock) {
55             engineCtx = NativeCrypto.ENGINE_by_id(engine);
56             if (engineCtx == 0) {
57                 throw new IllegalArgumentException("Unknown ENGINE id: " + engine);
58             }
59 
60             NativeCrypto.ENGINE_add(engineCtx);
61         }
62 
63         return new OpenSSLEngine(engineCtx);
64     }
65 
66     /**
67      * Used for BoringSSL. It doesn't use ENGINEs so there is no native pointer
68      * to keep track of.
69      */
OpenSSLEngine()70     private OpenSSLEngine() {
71         ctx = 0L;
72     }
73 
74     /**
75      * Used when OpenSSL is in use. It uses an ENGINE instance so we need to
76      * keep track if the native pointer for later freeing.
77      *
78      * @param engineCtx the ENGINE's native handle
79      */
OpenSSLEngine(long engineCtx)80     private OpenSSLEngine(long engineCtx) {
81         ctx = engineCtx;
82 
83         if (NativeCrypto.ENGINE_init(engineCtx) == 0) {
84             NativeCrypto.ENGINE_free(engineCtx);
85             throw new IllegalArgumentException("Could not initialize engine");
86         }
87     }
88 
getPrivateKeyById(String id)89     public PrivateKey getPrivateKeyById(String id) throws InvalidKeyException {
90         if (id == null) {
91             throw new NullPointerException("id == null");
92         }
93 
94         final long keyRef = NativeCrypto.ENGINE_load_private_key(ctx, id);
95         if (keyRef == 0) {
96             return null;
97         }
98 
99         OpenSSLKey pkey = new OpenSSLKey(keyRef, this, id);
100         try {
101             return pkey.getPrivateKey();
102         } catch (NoSuchAlgorithmException e) {
103             throw new InvalidKeyException(e);
104         }
105     }
106 
getEngineContext()107     long getEngineContext() {
108         return ctx;
109     }
110 
111     @Override
finalize()112     protected void finalize() throws Throwable {
113         try {
114             if (!NativeCrypto.isBoringSSL) {
115                 NativeCrypto.ENGINE_finish(ctx);
116                 NativeCrypto.ENGINE_free(ctx);
117             }
118         } finally {
119             super.finalize();
120         }
121     }
122 
123     @Override
equals(Object o)124     public boolean equals(Object o) {
125         if (o == this) {
126             return true;
127         }
128 
129         if (!(o instanceof OpenSSLEngine)) {
130             return false;
131         }
132 
133         OpenSSLEngine other = (OpenSSLEngine) o;
134 
135         if (other.getEngineContext() == ctx) {
136             return true;
137         }
138 
139         final String id = NativeCrypto.ENGINE_get_id(ctx);
140         if (id == null) {
141             return false;
142         }
143 
144         return id.equals(NativeCrypto.ENGINE_get_id(other.getEngineContext()));
145     }
146 
147     @Override
hashCode()148     public int hashCode() {
149       return (int) ctx;
150     }
151 }
152