1fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root/* 2fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * Copyright (C) 2013 The Android Open Source Project 3fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * 4fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 5fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * you may not use this file except in compliance with the License. 6fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * You may obtain a copy of the License at 7fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * 8fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 9fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * 10fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * Unless required by applicable law or agreed to in writing, software 11fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 12fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * See the License for the specific language governing permissions and 14fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root * limitations under the License. 15fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root */ 16fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt; 18fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 19fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Rootimport java.io.IOException; 20fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Rootimport java.io.NotSerializableException; 21fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Rootimport java.io.ObjectInputStream; 22fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Rootimport java.io.ObjectOutputStream; 23fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Rootimport java.security.InvalidKeyException; 24fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Rootimport java.util.Arrays; 25fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 26fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Rootimport javax.crypto.SecretKey; 27fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 28fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Rootpublic class OpenSSLSecretKey implements SecretKey, OpenSSLKeyHolder { 29fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root private static final long serialVersionUID = 1831053062911514589L; 30fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 31fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root private final String algorithm; 32fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root private final int type; 33fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root private final byte[] encoded; 34fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 35fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root private transient OpenSSLKey key; 36fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 37fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public OpenSSLSecretKey(String algorithm, byte[] encoded) { 38fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root this.algorithm = algorithm; 39fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root this.encoded = encoded; 40fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 41fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root type = NativeCrypto.EVP_PKEY_HMAC; 42fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_mac_key(type, encoded)); 43fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 44fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 45fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public OpenSSLSecretKey(String algorithm, OpenSSLKey key) { 46fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root this.algorithm = algorithm; 47fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root this.key = key; 48fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 49fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root type = NativeCrypto.EVP_PKEY_type(key.getPkeyContext()); 50fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root encoded = null; 51fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 52fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 53fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public static OpenSSLKey getInstance(SecretKey key) throws InvalidKeyException { 54fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root try { 55fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return new OpenSSLKey(NativeCrypto.EVP_PKEY_new_mac_key(NativeCrypto.EVP_PKEY_HMAC, 56fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root key.getEncoded())); 57fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } catch (Exception e) { 58fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root throw new InvalidKeyException(e); 59fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 60fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 61fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 62fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root @Override 63fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public String getAlgorithm() { 64fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return algorithm; 65fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 66fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 67fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root @Override 68fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public String getFormat() { 69fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root if (key.isEngineBased()) { 70fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return null; 71fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 72fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 73fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return "RAW"; 74fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 75fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 76fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root @Override 77fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public byte[] getEncoded() { 78fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root if (key.isEngineBased()) { 79fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return null; 80fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 81fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 82fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return encoded; 83fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 84fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 85fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root @Override 86fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public OpenSSLKey getOpenSSLKey() { 87fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return key; 88fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 89fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 90fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root @Override 91fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public boolean equals(Object o) { 92fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root if (o == this) { 93fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return true; 94fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 95fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 96fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root if (!(o instanceof SecretKey)) { 97fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return false; 98fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 99fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 100fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root SecretKey other = (SecretKey) o; 101fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root if (!algorithm.equals(other.getAlgorithm())) { 102fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return false; 103fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 104fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 105fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root if (o instanceof OpenSSLSecretKey) { 106fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root OpenSSLSecretKey otherOpenSSL = (OpenSSLSecretKey) o; 107fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return key.equals(otherOpenSSL.getOpenSSLKey()); 108fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } else if (key.isEngineBased()) { 109fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return false; 110fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 111fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 112fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root if (!getFormat().equals(other.getFormat())) { 113fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return false; 114fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 115fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 116fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return Arrays.equals(encoded, other.getEncoded()); 117fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 118fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 119fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root @Override 120fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root public int hashCode() { 121fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root return key.hashCode(); 122fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 123fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 124fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 125fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root stream.defaultReadObject(); 126fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 127fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root key = new OpenSSLKey(NativeCrypto.EVP_PKEY_new_mac_key(type, encoded)); 128fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 129fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 130fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root private void writeObject(ObjectOutputStream stream) throws IOException { 131fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root if (getOpenSSLKey().isEngineBased()) { 132fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root throw new NotSerializableException("engine-based keys can not be serialized"); 133fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 134fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root 135fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root stream.defaultWriteObject(); 136fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root } 137fe6f8e653aa8e0955b7ee0d40b4476351c7842c9Kenny Root} 138