• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.org.conscrypt.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      */
OpenSSLDigest(String algorithm, long evp_md, int size, int blockSize)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 
getAlgorithmName()70     public String getAlgorithmName() {
71         return algorithm;
72     }
73 
getDigestSize()74     public int getDigestSize() {
75         return size;
76     }
77 
getByteLength()78     public int getByteLength() {
79         return blockSize;
80     }
81 
reset()82     public void reset() {
83         free();
84     }
85 
update(byte in)86     public void update(byte in) {
87         singleByte[0] = in;
88         update(singleByte, 0, 1);
89     }
90 
update(byte[] in, int inOff, int len)91     public void update(byte[] in, int inOff, int len) {
92         NativeCrypto.EVP_DigestUpdate(getCtx(), in, inOff, len);
93     }
94 
doFinal(byte[] out, int outOff)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 
getCtx()102     private long getCtx() {
103         if (ctx == 0) {
104             ctx = NativeCrypto.EVP_DigestInit(evp_md);
105         }
106         return ctx;
107     }
108 
free()109     private void free() {
110         if (ctx != 0) {
111             NativeCrypto.EVP_MD_CTX_destroy(ctx);
112             ctx = 0;
113         }
114     }
115 
116     @Override
finalize()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);
MD5()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);
SHA1()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);
SHA256()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);
SHA384()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);
SHA512()157         public SHA512() { super("SHA-512", EVP_MD, SIZE, BLOCK_SIZE); }
158     }
159 }
160