1720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root/* 2720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * Copyright (C) 2012 The Android Open Source Project 3720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * 4720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 5720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * you may not use this file except in compliance with the License. 6720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * You may obtain a copy of the License at 7720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * 8720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 9720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * 10720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * Unless required by applicable law or agreed to in writing, software 11720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 12720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * See the License for the specific language governing permissions and 14720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root * limitations under the License. 15720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root */ 16720b2bf27d36d92aa7f39ab627968aa7346e7904Kenny Root 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt; 18e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 19e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubinimport java.nio.ByteBuffer; 20e4b82368b271aa959783814dde0087c84aed53b5Kenny Rootimport java.security.InvalidAlgorithmParameterException; 21e4b82368b271aa959783814dde0087c84aed53b5Kenny Rootimport java.security.InvalidKeyException; 22e4b82368b271aa959783814dde0087c84aed53b5Kenny Rootimport java.security.Key; 23e4b82368b271aa959783814dde0087c84aed53b5Kenny Rootimport java.security.NoSuchAlgorithmException; 24e4b82368b271aa959783814dde0087c84aed53b5Kenny Rootimport java.security.spec.AlgorithmParameterSpec; 25e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 26e4b82368b271aa959783814dde0087c84aed53b5Kenny Rootimport javax.crypto.MacSpi; 27e4b82368b271aa959783814dde0087c84aed53b5Kenny Rootimport javax.crypto.SecretKey; 28e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 29e4b82368b271aa959783814dde0087c84aed53b5Kenny Rootpublic abstract class OpenSSLMac extends MacSpi { 30a00142199f81acd00671d07d288845b5a5f15381David Benjamin private NativeRef.HMAC_CTX ctx; 31e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 32e4b82368b271aa959783814dde0087c84aed53b5Kenny Root /** 33e4b82368b271aa959783814dde0087c84aed53b5Kenny Root * Holds the EVP_MD for the hashing algorithm, e.g. 34e4b82368b271aa959783814dde0087c84aed53b5Kenny Root * EVP_get_digestbyname("sha1"); 35e4b82368b271aa959783814dde0087c84aed53b5Kenny Root */ 3638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private final long evp_md; 37e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 38e4b82368b271aa959783814dde0087c84aed53b5Kenny Root /** 39e4b82368b271aa959783814dde0087c84aed53b5Kenny Root * The secret key used in this keyed MAC. 40e4b82368b271aa959783814dde0087c84aed53b5Kenny Root */ 41a00142199f81acd00671d07d288845b5a5f15381David Benjamin private byte[] keyBytes; 42e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 43e4b82368b271aa959783814dde0087c84aed53b5Kenny Root /** 44e4b82368b271aa959783814dde0087c84aed53b5Kenny Root * Holds the output size of the message digest. 45e4b82368b271aa959783814dde0087c84aed53b5Kenny Root */ 46e4b82368b271aa959783814dde0087c84aed53b5Kenny Root private final int size; 47e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 48e4b82368b271aa959783814dde0087c84aed53b5Kenny Root /** 49e4b82368b271aa959783814dde0087c84aed53b5Kenny Root * Holds a dummy buffer for writing single bytes to the digest. 50e4b82368b271aa959783814dde0087c84aed53b5Kenny Root */ 51e4b82368b271aa959783814dde0087c84aed53b5Kenny Root private final byte[] singleByte = new byte[1]; 52e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 53a00142199f81acd00671d07d288845b5a5f15381David Benjamin private OpenSSLMac(long evp_md, int size) { 54e4b82368b271aa959783814dde0087c84aed53b5Kenny Root this.evp_md = evp_md; 55e4b82368b271aa959783814dde0087c84aed53b5Kenny Root this.size = size; 56e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 57e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 58e4b82368b271aa959783814dde0087c84aed53b5Kenny Root @Override 59e4b82368b271aa959783814dde0087c84aed53b5Kenny Root protected int engineGetMacLength() { 60e4b82368b271aa959783814dde0087c84aed53b5Kenny Root return size; 61e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 62e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 63e4b82368b271aa959783814dde0087c84aed53b5Kenny Root @Override 64e4b82368b271aa959783814dde0087c84aed53b5Kenny Root protected void engineInit(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, 65e4b82368b271aa959783814dde0087c84aed53b5Kenny Root InvalidAlgorithmParameterException { 66e4b82368b271aa959783814dde0087c84aed53b5Kenny Root if (!(key instanceof SecretKey)) { 67e4b82368b271aa959783814dde0087c84aed53b5Kenny Root throw new InvalidKeyException("key must be a SecretKey"); 68e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 69e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 70e4b82368b271aa959783814dde0087c84aed53b5Kenny Root if (params != null) { 71e4b82368b271aa959783814dde0087c84aed53b5Kenny Root throw new InvalidAlgorithmParameterException("unknown parameter type"); 72e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 73e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 74a00142199f81acd00671d07d288845b5a5f15381David Benjamin keyBytes = key.getEncoded(); 75a00142199f81acd00671d07d288845b5a5f15381David Benjamin if (keyBytes == null) { 76a00142199f81acd00671d07d288845b5a5f15381David Benjamin throw new InvalidKeyException("key cannot be encoded"); 77e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 78e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 79652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root resetContext(); 80e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 81e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 82652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root private final void resetContext() { 83a00142199f81acd00671d07d288845b5a5f15381David Benjamin NativeRef.HMAC_CTX ctxLocal = new NativeRef.HMAC_CTX(NativeCrypto.HMAC_CTX_new()); 84a00142199f81acd00671d07d288845b5a5f15381David Benjamin if (keyBytes != null) { 85a00142199f81acd00671d07d288845b5a5f15381David Benjamin NativeCrypto.HMAC_Init_ex(ctxLocal, keyBytes, evp_md); 86c41697ab2043f5b0e0f86b6731519eb72e3569e5Kenny Root } 87652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root 88652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root this.ctx = ctxLocal; 89e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 90e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 91e4b82368b271aa959783814dde0087c84aed53b5Kenny Root @Override 92e4b82368b271aa959783814dde0087c84aed53b5Kenny Root protected void engineUpdate(byte input) { 93e4b82368b271aa959783814dde0087c84aed53b5Kenny Root singleByte[0] = input; 94e4b82368b271aa959783814dde0087c84aed53b5Kenny Root engineUpdate(singleByte, 0, 1); 95e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 96e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 97e4b82368b271aa959783814dde0087c84aed53b5Kenny Root @Override 98e4b82368b271aa959783814dde0087c84aed53b5Kenny Root protected void engineUpdate(byte[] input, int offset, int len) { 99a00142199f81acd00671d07d288845b5a5f15381David Benjamin final NativeRef.HMAC_CTX ctxLocal = ctx; 100a00142199f81acd00671d07d288845b5a5f15381David Benjamin NativeCrypto.HMAC_Update(ctxLocal, input, offset, len); 101e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 102e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 103e4b82368b271aa959783814dde0087c84aed53b5Kenny Root @Override 104e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin protected void engineUpdate(ByteBuffer input) { 105e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin // Optimization: Avoid copying/allocation for direct buffers because their contents are 106e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin // stored as a contiguous region in memory and thus can be efficiently accessed from native 107e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin // code. 108e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin 109e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin if (!input.hasRemaining()) { 110e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin return; 111e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin } 112e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin 113e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin if (!input.isDirect()) { 114e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin super.engineUpdate(input); 115e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin return; 116e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin } 117e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin 118e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin long baseAddress = NativeCrypto.getDirectBufferAddress(input); 119e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin if (baseAddress == 0) { 120e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin // Direct buffer's contents can't be accessed from JNI -- superclass's implementation 121e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin // is good enough to handle this. 122e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin super.engineUpdate(input); 123e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin return; 124e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin } 125e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin 126e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin // MAC the contents between Buffer's position and limit (remaining() number of bytes) 127e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin int position = input.position(); 12849ebea12f4954f3dbcd16a33a8fa98532d29f8c9Alex Klyubin if (position < 0) { 12949ebea12f4954f3dbcd16a33a8fa98532d29f8c9Alex Klyubin throw new RuntimeException("Negative position"); 130e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin } 13149ebea12f4954f3dbcd16a33a8fa98532d29f8c9Alex Klyubin long ptr = baseAddress + position; 132e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin int len = input.remaining(); 13349ebea12f4954f3dbcd16a33a8fa98532d29f8c9Alex Klyubin if (len < 0) { 13449ebea12f4954f3dbcd16a33a8fa98532d29f8c9Alex Klyubin throw new RuntimeException("Negative remaining amount"); 135e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin } 136e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin 137e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin final NativeRef.HMAC_CTX ctxLocal = ctx; 138e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin NativeCrypto.HMAC_UpdateDirect(ctxLocal, ptr, len); 139e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin input.position(position + len); 140e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin } 141e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin 142e33d066caa6fff22e17e807abcdff9bc4f746bb0Alex Klyubin @Override 143e4b82368b271aa959783814dde0087c84aed53b5Kenny Root protected byte[] engineDoFinal() { 144a00142199f81acd00671d07d288845b5a5f15381David Benjamin final NativeRef.HMAC_CTX ctxLocal = ctx; 145a00142199f81acd00671d07d288845b5a5f15381David Benjamin final byte[] output = NativeCrypto.HMAC_Final(ctxLocal); 146652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root resetContext(); 147e4b82368b271aa959783814dde0087c84aed53b5Kenny Root return output; 148e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 149e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 150e4b82368b271aa959783814dde0087c84aed53b5Kenny Root @Override 151e4b82368b271aa959783814dde0087c84aed53b5Kenny Root protected void engineReset() { 152652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root resetContext(); 153e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 154e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 155e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public static class HmacMD5 extends OpenSSLMac { 15638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("md5"); 157e4b82368b271aa959783814dde0087c84aed53b5Kenny Root private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 158e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 159e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public HmacMD5() { 160a00142199f81acd00671d07d288845b5a5f15381David Benjamin super(EVP_MD, SIZE); 161e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 162e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 163e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 164e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public static class HmacSHA1 extends OpenSSLMac { 16538c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha1"); 166e4b82368b271aa959783814dde0087c84aed53b5Kenny Root private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 167e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 168e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public HmacSHA1() { 169a00142199f81acd00671d07d288845b5a5f15381David Benjamin super(EVP_MD, SIZE); 170e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 171e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 172e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 173d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root public static class HmacSHA224 extends OpenSSLMac { 174d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha224"); 175d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 176d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root 177d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root public HmacSHA224() throws NoSuchAlgorithmException { 178a00142199f81acd00671d07d288845b5a5f15381David Benjamin super(EVP_MD, SIZE); 179d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root } 180d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root } 181d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root 182e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public static class HmacSHA256 extends OpenSSLMac { 18338c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha256"); 184e4b82368b271aa959783814dde0087c84aed53b5Kenny Root private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 185e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 186e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public HmacSHA256() throws NoSuchAlgorithmException { 187a00142199f81acd00671d07d288845b5a5f15381David Benjamin super(EVP_MD, SIZE); 188e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 189e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 190e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 191e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public static class HmacSHA384 extends OpenSSLMac { 19238c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha384"); 193e4b82368b271aa959783814dde0087c84aed53b5Kenny Root private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 194e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 195e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public HmacSHA384() throws NoSuchAlgorithmException { 196a00142199f81acd00671d07d288845b5a5f15381David Benjamin super(EVP_MD, SIZE); 197e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 198e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 199e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 200e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public static class HmacSHA512 extends OpenSSLMac { 20138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha512"); 202e4b82368b271aa959783814dde0087c84aed53b5Kenny Root private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 203e4b82368b271aa959783814dde0087c84aed53b5Kenny Root 204e4b82368b271aa959783814dde0087c84aed53b5Kenny Root public HmacSHA512() { 205a00142199f81acd00671d07d288845b5a5f15381David Benjamin super(EVP_MD, SIZE); 206e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 207e4b82368b271aa959783814dde0087c84aed53b5Kenny Root } 208e4b82368b271aa959783814dde0087c84aed53b5Kenny Root} 209