1 /* 2 * Copyright (C) 2008 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.bouncycastle.crypto.digests; 18 19 import org.apache.harmony.xnet.provider.jsse.NativeCrypto; 20 import org.bouncycastle.crypto.ExtendedDigest; 21 22 /** 23 * Implements the BouncyCastle Digest interface using OpenSSL's EVP API. 24 */ 25 public class OpenSSLDigest implements ExtendedDigest { 26 27 /** 28 * Holds the standard name of the hashing algorithm, e.g. "SHA-1"; 29 */ 30 private final String algorithm; 31 32 /** 33 * Holds the EVP_MD for the hashing algorithm, e.g. EVP_get_digestbyname("sha1"); 34 */ 35 private final long evp_md; 36 37 /** 38 * Holds the output size of the message digest. 39 */ 40 private final int size; 41 42 /** 43 * Holds the block size of the message digest. 44 */ 45 private final int blockSize; 46 47 /** 48 * Holds a pointer to the native message digest context. It is 49 * lazily initialized to avoid having to reallocate on reset when 50 * its unlikely to be reused. 51 */ 52 private long ctx; 53 54 /** 55 * Holds a dummy buffer for writing single bytes to the digest. 56 */ 57 private final byte[] singleByte = new byte[1]; 58 59 /** 60 * Creates a new OpenSSLMessageDigest instance for the given algorithm 61 * name. 62 */ 63 private OpenSSLDigest(String algorithm, long evp_md, int size, int blockSize) { 64 this.algorithm = algorithm; 65 this.evp_md = evp_md; 66 this.size = size; 67 this.blockSize = blockSize; 68 } 69 70 public String getAlgorithmName() { 71 return algorithm; 72 } 73 74 public int getDigestSize() { 75 return size; 76 } 77 78 public int getByteLength() { 79 return blockSize; 80 } 81 82 public void reset() { 83 free(); 84 } 85 86 public void update(byte in) { 87 singleByte[0] = in; 88 update(singleByte, 0, 1); 89 } 90 91 public void update(byte[] in, int inOff, int len) { 92 NativeCrypto.EVP_DigestUpdate(getCtx(), in, inOff, len); 93 } 94 95 public int doFinal(byte[] out, int outOff) { 96 int i = NativeCrypto.EVP_DigestFinal(getCtx(), out, outOff); 97 ctx = 0; // EVP_DigestFinal frees the context as a side effect 98 reset(); 99 return i; 100 } 101 102 private long getCtx() { 103 if (ctx == 0) { 104 ctx = NativeCrypto.EVP_DigestInit(evp_md); 105 } 106 return ctx; 107 } 108 109 private void free() { 110 if (ctx != 0) { 111 NativeCrypto.EVP_MD_CTX_destroy(ctx); 112 ctx = 0; 113 } 114 } 115 116 @Override 117 protected void finalize() throws Throwable { 118 try { 119 free(); 120 } finally { 121 super.finalize(); 122 } 123 } 124 125 public static class MD5 extends OpenSSLDigest { 126 private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("md5"); 127 private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 128 private static final int BLOCK_SIZE = NativeCrypto.EVP_MD_block_size(EVP_MD); 129 public MD5() { super("MD5", EVP_MD, SIZE, BLOCK_SIZE); } 130 } 131 132 public static class SHA1 extends OpenSSLDigest { 133 private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha1"); 134 private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 135 private static final int BLOCK_SIZE = NativeCrypto.EVP_MD_block_size(EVP_MD); 136 public SHA1() { super("SHA-1", EVP_MD, SIZE, BLOCK_SIZE); } 137 } 138 139 public static class SHA256 extends OpenSSLDigest { 140 private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha256"); 141 private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 142 private static final int BLOCK_SIZE = NativeCrypto.EVP_MD_block_size(EVP_MD); 143 public SHA256() { super("SHA-256", EVP_MD, SIZE, BLOCK_SIZE); } 144 } 145 146 public static class SHA384 extends OpenSSLDigest { 147 private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha384"); 148 private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 149 private static final int BLOCK_SIZE = NativeCrypto.EVP_MD_block_size(EVP_MD); 150 public SHA384() { super("SHA-384", EVP_MD, SIZE, BLOCK_SIZE); } 151 } 152 153 public static class SHA512 extends OpenSSLDigest { 154 private static final long EVP_MD = NativeCrypto.EVP_get_digestbyname("sha512"); 155 private static final int SIZE = NativeCrypto.EVP_MD_size(EVP_MD); 156 private static final int BLOCK_SIZE = NativeCrypto.EVP_MD_block_size(EVP_MD); 157 public SHA512() { super("SHA-512", EVP_MD, SIZE, BLOCK_SIZE); } 158 } 159 } 160