1db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom/* 2db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * Copyright (C) 2008 The Android Open Source Project 3db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * 4db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * you may not use this file except in compliance with the License. 6db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * You may obtain a copy of the License at 7db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * 8db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * 10db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 11db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * See the License for the specific language governing permissions and 14db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom * limitations under the License. 15db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom */ 16db9ae4fb599a534bd0703bec27fccd4493b04be7Brian Carlstrom 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt; 1808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 19652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Rootimport java.security.MessageDigestSpi; 2008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.NoSuchAlgorithmException; 2108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 2208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/** 2308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Implements the JDK MessageDigest interface using OpenSSL's EVP API. 2408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 2588b56b0666fe3a702da4edc7b5b58266033c5871Kenny Rootpublic class OpenSSLMessageDigestJDK extends MessageDigestSpi implements Cloneable { 26652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root private OpenSSLDigestContext ctx; 2708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 2808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 29079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom * Holds the EVP_MD for the hashing algorithm, e.g. EVP_get_digestbyname("sha1"); 30e47676a3143deb907b770a461f42d865f767932cBrian Carlstrom */ 3138c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private final long evp_md; 32079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom 33079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom /** 34079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom * Holds the output size of the message digest. 35079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom */ 36079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom private final int size; 37e47676a3143deb907b770a461f42d865f767932cBrian Carlstrom 38e47676a3143deb907b770a461f42d865f767932cBrian Carlstrom /** 3908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Holds a dummy buffer for writing single bytes to the digest. 4008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 415763f15af2a820056075dd9007d03d3e855a27adBrian Carlstrom private final byte[] singleByte = new byte[1]; 4208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 4308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 44652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root * Creates a new OpenSSLMessageDigest instance for the given algorithm name. 4508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 46652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root private OpenSSLMessageDigestJDK(long evp_md, int size) throws NoSuchAlgorithmException { 47079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom this.evp_md = evp_md; 48079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom this.size = size; 49652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root 50652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root resetContext(); 51652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root } 52652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root 5388b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root private OpenSSLMessageDigestJDK(long evp_md, int size, OpenSSLDigestContext ctx) { 5488b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root this.evp_md = evp_md; 5588b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root this.size = size; 5688b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root this.ctx = ctx; 5788b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root } 5888b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root 59652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root private final void resetContext() { 60652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root OpenSSLDigestContext ctxLocal = new OpenSSLDigestContext(NativeCrypto.EVP_MD_CTX_create()); 61652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root NativeCrypto.EVP_MD_CTX_init(ctxLocal); 62652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root NativeCrypto.EVP_DigestInit(ctxLocal, evp_md); 63652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root ctx = ctxLocal; 6408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project @Override 6708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected void engineReset() { 68652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root resetContext(); 6908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 7008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project @Override 7208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected int engineGetDigestLength() { 73079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom return size; 7408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 7508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project @Override 7708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected void engineUpdate(byte input) { 7808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project singleByte[0] = input; 7908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project engineUpdate(singleByte, 0, 1); 8008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 8108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project @Override 8308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected void engineUpdate(byte[] input, int offset, int len) { 84652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root NativeCrypto.EVP_DigestUpdate(ctx, input, offset, len); 85079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom } 86079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom 87079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom @Override 88079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom protected byte[] engineDigest() { 89652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root final byte[] result = new byte[size]; 90652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root NativeCrypto.EVP_DigestFinal(ctx, result, 0); 91652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root resetContext(); 92079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom return result; 9308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 9408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 952ecdfa100af0c18814445608ac7b2bc1e11ef4b2Brian Carlstrom public static class MD5 extends OpenSSLMessageDigestJDK { 9638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("md5"); 97079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 9808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public MD5() throws NoSuchAlgorithmException { 99652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root super(EVP_MD, SIZE); 10008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 10108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 10273f1fad27323ed00b318de046cfe43236625af09Elliott Hughes 1032ecdfa100af0c18814445608ac7b2bc1e11ef4b2Brian Carlstrom public static class SHA1 extends OpenSSLMessageDigestJDK { 10438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha1"); 105079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 10608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public SHA1() throws NoSuchAlgorithmException { 107652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root super(EVP_MD, SIZE); 10808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 10908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 11073f1fad27323ed00b318de046cfe43236625af09Elliott Hughes 111d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root public static class SHA224 extends OpenSSLMessageDigestJDK { 112d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha224"); 113d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 114d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root public SHA224() throws NoSuchAlgorithmException { 115652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root super(EVP_MD, SIZE); 116d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root } 117d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root } 118d2db2c558ef6afc14d59f4a6b547598ff3973597Kenny Root 1192ecdfa100af0c18814445608ac7b2bc1e11ef4b2Brian Carlstrom public static class SHA256 extends OpenSSLMessageDigestJDK { 12038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha256"); 121079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 12208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public SHA256() throws NoSuchAlgorithmException { 123652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root super(EVP_MD, SIZE); 12408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 12508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 126af957f4171aee023d696a514744942d6a003bdbfBrian Carlstrom 1272ecdfa100af0c18814445608ac7b2bc1e11ef4b2Brian Carlstrom public static class SHA384 extends OpenSSLMessageDigestJDK { 12838c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha384"); 129079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 130af957f4171aee023d696a514744942d6a003bdbfBrian Carlstrom public SHA384() throws NoSuchAlgorithmException { 131652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root super(EVP_MD, SIZE); 132af957f4171aee023d696a514744942d6a003bdbfBrian Carlstrom } 133af957f4171aee023d696a514744942d6a003bdbfBrian Carlstrom } 134af957f4171aee023d696a514744942d6a003bdbfBrian Carlstrom 1352ecdfa100af0c18814445608ac7b2bc1e11ef4b2Brian Carlstrom public static class SHA512 extends OpenSSLMessageDigestJDK { 13638c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha512"); 137079fab65ece9d6c13d3f67206550985f5d8439fdBrian Carlstrom private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 138af957f4171aee023d696a514744942d6a003bdbfBrian Carlstrom public SHA512() throws NoSuchAlgorithmException { 139652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root super(EVP_MD, SIZE); 140af957f4171aee023d696a514744942d6a003bdbfBrian Carlstrom } 141af957f4171aee023d696a514744942d6a003bdbfBrian Carlstrom } 14288b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root 14388b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root @Override 14488b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root public Object clone() { 14588b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root OpenSSLDigestContext ctxCopy = new OpenSSLDigestContext(NativeCrypto.EVP_MD_CTX_create()); 14688b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root NativeCrypto.EVP_MD_CTX_init(ctxCopy); 14788b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root NativeCrypto.EVP_MD_CTX_copy(ctxCopy, ctx); 14888b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root return new OpenSSLMessageDigestJDK(evp_md, size, ctxCopy); 14988b56b0666fe3a702da4edc7b5b58266033c5871Kenny Root } 15008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project} 151