1 module hunt.net.secure.conscrypt.OpenSSLKey; 2 3 // // dfmt off 4 // version(WITH_HUNT_SECURITY): 5 // // dfmt on 6 7 // import hunt.net.secure.conscrypt.NativeCrypto; 8 // import hunt.net.secure.conscrypt.NativeRef; 9 // import hunt.net.secure.conscrypt.OpenSSLKeyHolder; 10 11 // import hunt.security.Key; 12 13 // import hunt.Exceptions; 14 // import hunt.text.Common; 15 16 // /** 17 // * Represents a BoringSSL {@code EVP_PKEY}. 18 // */ 19 // final class OpenSSLKey { 20 // private NativeRef.EVP_PKEY ctx; 21 22 // private bool wrapped; 23 24 // this(long ctx) { 25 // this(ctx, false); 26 // } 27 28 // this(long ctx, bool wrapped) { 29 // this.ctx = new NativeRef.EVP_PKEY(ctx); 30 // this.wrapped = wrapped; 31 // } 32 33 // /** 34 // * Returns the EVP_PKEY context for use in JNI calls. 35 // */ 36 // NativeRef.EVP_PKEY getNativeRef() { 37 // return ctx; 38 // } 39 40 // bool isWrapped() { 41 // return wrapped; 42 // } 43 44 // // static OpenSSLKey fromPrivateKey(PrivateKey key) { 45 // // if (key instanceof OpenSSLKeyHolder) { 46 // // return ((OpenSSLKeyHolder) key).getOpenSSLKey(); 47 // // } 48 49 // // string keyFormat = key.getFormat(); 50 // // if (keyFormat is null) { 51 // // return wrapPrivateKey(key); 52 // // } else if (!"PKCS#8".equals(key.getFormat())) { 53 // // throw new InvalidKeyException("Unknown key format " ~ keyFormat); 54 // // } 55 56 // // byte[] encoded = key.getEncoded(); 57 // // if (encoded is null) { 58 // // throw new InvalidKeyException("Key encoding is null"); 59 // // } 60 61 // // try { 62 // // return new OpenSSLKey(NativeCrypto.EVP_parse_private_key(key.getEncoded())); 63 // // } catch (ParsingException e) { 64 // // throw new InvalidKeyException(e); 65 // // } 66 // // } 67 68 // // /** 69 // // * Parse a private key in PEM encoding from the provided input stream. 70 // // * 71 // // * @throws InvalidKeyException if parsing fails 72 // // */ 73 // // static OpenSSLKey fromPrivateKeyPemInputStream(InputStream is) 74 // // { 75 // // OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true); 76 // // try { 77 // // long keyCtx = NativeCrypto.PEM_read_bio_PrivateKey(bis.getBioContext()); 78 // // if (keyCtx == 0L) { 79 // // return null; 80 // // } 81 82 // // return new OpenSSLKey(keyCtx); 83 // // } catch (Exception e) { 84 // // throw new InvalidKeyException(e); 85 // // } finally { 86 // // bis.release(); 87 // // } 88 // // } 89 90 // /** 91 // * Gets an {@code OpenSSLKey} instance backed by the provided private key. The resulting key is 92 // * usable only by this provider's TLS/SSL stack. 93 // * 94 // * @param privateKey private key. 95 // * @param publicKey corresponding key or {@code null} if not available. Some opaque 96 // * private keys cannot be used by the TLS/SSL stack without the key. 97 // */ 98 // // static OpenSSLKey fromPrivateKeyForTLSStackOnly( 99 // // PrivateKey privateKey, PublicKey publicKey) { 100 // // OpenSSLKey result = getOpenSSLKey(privateKey); 101 // // if (result !is null) { 102 // // return result; 103 // // } 104 105 // // result = fromKeyMaterial(privateKey); 106 // // if (result !is null) { 107 // // return result; 108 // // } 109 110 // // return wrapJCAPrivateKeyForTLSStackOnly(privateKey, publicKey); 111 // // } 112 113 // // /** 114 // // * Gets an {@code OpenSSLKey} instance backed by the provided EC private key. The resulting key 115 // // * is usable only by this provider's TLS/SSL stack. 116 // // * 117 // // * @param key private key. 118 // // * @param ecParams EC parameters {@code null} if not available. Some opaque private keys cannot 119 // // * be used by the TLS/SSL stack without the parameters because the private key itself 120 // // * might not expose the parameters. 121 // // */ 122 // // static OpenSSLKey fromECPrivateKeyForTLSStackOnly( 123 // // PrivateKey key, ECParameterSpec ecParams) { 124 // // OpenSSLKey result = getOpenSSLKey(key); 125 // // if (result !is null) { 126 // // return result; 127 // // } 128 129 // // result = fromKeyMaterial(key); 130 // // if (result !is null) { 131 // // return result; 132 // // } 133 134 // // return OpenSSLECPrivateKey.wrapJCAPrivateKeyForTLSStackOnly(key, ecParams); 135 // // } 136 137 // /** 138 // * Gets the {@code OpenSSLKey} instance of the provided key. 139 // * 140 // * @return instance or {@code null} if the {@code key} is not backed by OpenSSL's 141 // * {@code EVP_PKEY}. 142 // */ 143 // // private static OpenSSLKey getOpenSSLKey(PrivateKey key) { 144 // // OpenSSLKeyHolder keyHolder = cast(OpenSSLKeyHolder) key; 145 // // if (keyHolder !is null) { 146 // // return keyHolder.getOpenSSLKey(); 147 // // } 148 149 // // if ("RSA" == key.getAlgorithm()) { 150 // // implementationMissing(false); 151 // // // return Platform.wrapRsaKey(key); 152 // // } 153 154 // // return null; 155 // // } 156 157 // /** 158 // * Gets an {@code OpenSSLKey} instance initialized with the key material of the provided key. 159 // * 160 // * @return instance or {@code null} if the {@code key} does not export its key material in a 161 // * suitable format. 162 // */ 163 // // private static OpenSSLKey fromKeyMaterial(PrivateKey key) { 164 // // if (!"PKCS#8".equals(key.getFormat())) { 165 // // return null; 166 // // } 167 // // byte[] encoded = key.getEncoded(); 168 // // if (encoded is null) { 169 // // return null; 170 // // } 171 // // try { 172 // // version(Have_boringssl) return new OpenSSLKey(NativeCrypto.EVP_parse_private_key(encoded)); 173 // // version(Have_hunt_openssl) { 174 // // implementationMissing(false); 175 // // return null; 176 // // } 177 // // } catch (ParsingException e) { 178 // // throw new InvalidKeyException(e.msg); 179 // // } 180 // // } 181 182 // /** 183 // * Wraps the provided private key for use in the TLS/SSL stack only. Sign/decrypt operations 184 // * using the key will be delegated to the {@code Signature}/{@code Cipher} implementation of the 185 // * provider which accepts the key. 186 // */ 187 // // private static OpenSSLKey wrapJCAPrivateKeyForTLSStackOnly(PrivateKey privateKey, 188 // // PublicKey publicKey) { 189 // // string keyAlgorithm = privateKey.getAlgorithm(); 190 // // implementationMissing(false); 191 // // return null; 192 // // // if ("RSA".equals(keyAlgorithm)) { 193 // // // return OpenSSLRSAPrivateKey.wrapJCAPrivateKeyForTLSStackOnly(privateKey, publicKey); 194 // // // } else if ("EC".equals(keyAlgorithm)) { 195 // // // return OpenSSLECPrivateKey.wrapJCAPrivateKeyForTLSStackOnly(privateKey, publicKey); 196 // // // } else { 197 // // // throw new InvalidKeyException("Unsupported key algorithm: " ~ keyAlgorithm); 198 // // // } 199 // // } 200 201 // // private static OpenSSLKey wrapPrivateKey(PrivateKey key) { 202 // // if (key instanceof RSAPrivateKey) { 203 // // return OpenSSLRSAPrivateKey.wrapPlatformKey((RSAPrivateKey) key); 204 // // } else if (key instanceof ECPrivateKey) { 205 // // return OpenSSLECPrivateKey.wrapPlatformKey((ECPrivateKey) key); 206 // // } else { 207 // // throw new InvalidKeyException("Unknown key type: " ~ key.toString()); 208 // // } 209 // // } 210 211 // // static OpenSSLKey fromPublicKey(PublicKey key) { 212 // // if (key instanceof OpenSSLKeyHolder) { 213 // // return ((OpenSSLKeyHolder) key).getOpenSSLKey(); 214 // // } 215 216 // // if (!"X.509".equals(key.getFormat())) { 217 // // throw new InvalidKeyException("Unknown key format " ~ key.getFormat()); 218 // // } 219 220 // // byte[] encoded = key.getEncoded(); 221 // // if (encoded is null) { 222 // // throw new InvalidKeyException("Key encoding is null"); 223 // // } 224 225 // // try { 226 // // return new OpenSSLKey(NativeCrypto.EVP_parse_public_key(key.getEncoded())); 227 // // } catch (Exception e) { 228 // // throw new InvalidKeyException(e); 229 // // } 230 // // } 231 232 // // /** 233 // // * Parse a key in PEM encoding from the provided input stream. 234 // // * 235 // // * @throws InvalidKeyException if parsing fails 236 // // */ 237 // // static OpenSSLKey fromPublicKeyPemInputStream(InputStream is) 238 // // { 239 // // OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true); 240 // // try { 241 // // long keyCtx = NativeCrypto.PEM_read_bio_PUBKEY(bis.getBioContext()); 242 // // if (keyCtx == 0L) { 243 // // return null; 244 // // } 245 246 // // return new OpenSSLKey(keyCtx); 247 // // } catch (Exception e) { 248 // // throw new InvalidKeyException(e); 249 // // } finally { 250 // // bis.release(); 251 // // } 252 // // } 253 254 // // PublicKey getPublicKey() throws NoSuchAlgorithmException { 255 // // switch (NativeCrypto.EVP_PKEY_type(ctx)) { 256 // // case NativeConstants.EVP_PKEY_RSA: 257 // // return new OpenSSLRSAPublicKey(this); 258 // // case NativeConstants.EVP_PKEY_EC: 259 // // return new OpenSSLECPublicKey(this); 260 // // default: 261 // // throw new NoSuchAlgorithmException("unknown PKEY type"); 262 // // } 263 // // } 264 265 // // static PublicKey getPublicKey(X509EncodedKeySpec keySpec, int type) 266 // // throws InvalidKeySpecException { 267 // // X509EncodedKeySpec x509KeySpec = keySpec; 268 269 // // OpenSSLKey key; 270 // // try { 271 // // key = new OpenSSLKey(NativeCrypto.EVP_parse_public_key(x509KeySpec.getEncoded())); 272 // // } catch (Exception e) { 273 // // throw new InvalidKeySpecException(e); 274 // // } 275 276 // // if (NativeCrypto.EVP_PKEY_type(key.getNativeRef()) != type) { 277 // // throw new InvalidKeySpecException("Unexpected key type"); 278 // // } 279 280 // // try { 281 // // return key.getPublicKey(); 282 // // } catch (NoSuchAlgorithmException e) { 283 // // throw new InvalidKeySpecException(e); 284 // // } 285 // // } 286 287 // // PrivateKey getPrivateKey() throws NoSuchAlgorithmException { 288 // // switch (NativeCrypto.EVP_PKEY_type(ctx)) { 289 // // case NativeConstants.EVP_PKEY_RSA: 290 // // return new OpenSSLRSAPrivateKey(this); 291 // // case NativeConstants.EVP_PKEY_EC: 292 // // return new OpenSSLECPrivateKey(this); 293 // // default: 294 // // throw new NoSuchAlgorithmException("unknown PKEY type"); 295 // // } 296 // // } 297 298 // // static PrivateKey getPrivateKey(PKCS8EncodedKeySpec keySpec, int type) 299 // // throws InvalidKeySpecException { 300 // // PKCS8EncodedKeySpec pkcs8KeySpec = keySpec; 301 302 // // OpenSSLKey key; 303 // // try { 304 // // key = new OpenSSLKey(NativeCrypto.EVP_parse_private_key(pkcs8KeySpec.getEncoded())); 305 // // } catch (Exception e) { 306 // // throw new InvalidKeySpecException(e); 307 // // } 308 309 // // if (NativeCrypto.EVP_PKEY_type(key.getNativeRef()) != type) { 310 // // throw new InvalidKeySpecException("Unexpected key type"); 311 // // } 312 313 // // try { 314 // // return key.getPrivateKey(); 315 // // } catch (NoSuchAlgorithmException e) { 316 // // throw new InvalidKeySpecException(e); 317 // // } 318 // // } 319 320 // // override 321 // // bool equals(Object o) { 322 // // if (o == this) { 323 // // return true; 324 // // } 325 326 // // if (!(o instanceof OpenSSLKey)) { 327 // // return false; 328 // // } 329 330 // // OpenSSLKey other = (OpenSSLKey) o; 331 // // if (ctx.equals(other.getNativeRef())) { 332 // // return true; 333 // // } 334 335 // // return NativeCrypto.EVP_PKEY_cmp(ctx, other.getNativeRef()) == 1; 336 // // } 337 338 // // override 339 // // int hashCode() { 340 // // return ctx.hashCode(); 341 // // } 342 // }