Home | History | Annotate | Download | only in security
      1 /*
      2  * Copyright (C) 2009 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 package tests.security;
     17 
     18 import java.io.IOException;
     19 import java.io.InputStream;
     20 import java.security.MessageDigest;
     21 import java.security.NoSuchAlgorithmException;
     22 import junit.framework.TestCase;
     23 
     24 public abstract class MessageDigestTest extends TestCase {
     25 
     26     private String digestAlgorithmName;
     27 
     28     protected MessageDigestTest(String digestAlgorithmName) {
     29         super();
     30         this.digestAlgorithmName = digestAlgorithmName;
     31     }
     32 
     33     private MessageDigest digest;
     34     private InputStream sourceData;
     35     private byte[] checkDigest;
     36 
     37     @Override
     38     protected void setUp() throws Exception {
     39         super.setUp();
     40 
     41         this.source3 = getLongMessage(1000000);
     42         this.digest = getMessageDigest();
     43         this.sourceData = getSourceData();
     44         this.checkDigest = getCheckDigest();
     45     }
     46 
     47     @Override
     48     public void tearDown() throws Exception {
     49         super.tearDown();
     50 
     51         // This is critical. The MessageDigest tests consume a lot of memory due
     52         // to the 1 MB buffers being allocated. We need to make sure all data is
     53         // freed after each test. Otherwise the Android runtime simply dies at
     54         // some point.
     55         source1 = null;
     56         source2 = null;
     57         source3 = null;
     58 
     59         expected1 = null;
     60         expected2 = null;
     61         expected3 = null;
     62 
     63         digest = null;
     64         sourceData.close();
     65         sourceData = null;
     66         checkDigest = null;
     67 
     68         System.gc();
     69     }
     70 
     71     MessageDigest getMessageDigest() {
     72         try {
     73             return MessageDigest.getInstance(digestAlgorithmName);
     74         } catch (NoSuchAlgorithmException e) {
     75             fail("failed to get digest instance: " + e);
     76             return null;
     77         }
     78     }
     79 
     80     InputStream getSourceData() {
     81         InputStream sourceStream = getClass().getResourceAsStream(digestAlgorithmName + ".data");
     82         assertNotNull("digest source data not found: " + digestAlgorithmName, sourceStream);
     83         return sourceStream;
     84     }
     85 
     86     byte[] getCheckDigest() {
     87         InputStream checkDigestStream =
     88                 getClass().getResourceAsStream(digestAlgorithmName + ".check");
     89         byte[] checkDigest = new byte[digest.getDigestLength()];
     90         int read = 0;
     91         int index = 0;
     92         try {
     93             while ((read = checkDigestStream.read()) != -1) {
     94                 checkDigest[index++] = (byte)read;
     95             }
     96             checkDigestStream.close();
     97         } catch (IOException e) {
     98             fail("failed to read digest golden data: " + digestAlgorithmName);
     99         }
    100         return checkDigest;
    101     }
    102 
    103     public void testMessageDigest1() {
    104         byte[] buf = new byte[128];
    105         int read = 0;
    106         try {
    107             while ((read = sourceData.read(buf)) != -1) {
    108                 digest.update(buf, 0, read);
    109             }
    110             sourceData.close();
    111         } catch (IOException e) {
    112             fail("failed to read digest data");
    113         }
    114 
    115         byte[] computedDigest = digest.digest();
    116 
    117         assertNotNull("computed digest is is null", computedDigest);
    118         assertEquals("digest length mismatch", checkDigest.length, computedDigest.length);
    119 
    120         for (int i = 0; i < checkDigest.length; i++) {
    121             assertEquals("byte " + i + " of computed and check digest differ",
    122                          checkDigest[i], computedDigest[i]);
    123         }
    124 
    125     }
    126 
    127     public void testMessageDigest2() {
    128         int val;
    129         try {
    130             while ((val = sourceData.read()) != -1) {
    131                 digest.update((byte)val);
    132             }
    133             sourceData.close();
    134         } catch (IOException e) {
    135             fail("failed to read digest data");
    136         }
    137 
    138         byte[] computedDigest = digest.digest();
    139 
    140         assertNotNull("computed digest is is null", computedDigest);
    141         assertEquals("digest length mismatch", checkDigest.length, computedDigest.length);
    142         for (int i = 0; i < checkDigest.length; i++) {
    143             assertEquals("byte " + i + " of computed and check digest differ",
    144                          checkDigest[i], computedDigest[i]);
    145         }
    146 
    147     }
    148 
    149 
    150     /**
    151      * Official FIPS180-2 testcases
    152      */
    153 
    154     protected String source1;
    155     protected String source2;
    156     protected String source3;
    157     protected String expected1;
    158     protected String expected2;
    159     protected String expected3;
    160 
    161     String getLongMessage(int length) {
    162         StringBuilder sourceBuilder = new StringBuilder(length);
    163         for (int i = 0; i < length / 10; i++) {
    164             sourceBuilder.append("aaaaaaaaaa");
    165         }
    166         return sourceBuilder.toString();
    167     }
    168 
    169     public void testfips180_2_singleblock() {
    170 
    171         digest.update(source1.getBytes(), 0, source1.length());
    172 
    173         byte[] computedDigest = digest.digest();
    174 
    175         assertNotNull("computed digest is null", computedDigest);
    176 
    177         StringBuilder sb = new StringBuilder();
    178         for (int i = 0; i < computedDigest.length; i++) {
    179             String res = Integer.toHexString(computedDigest[i] & 0xFF);
    180             sb.append((res.length() == 1 ? "0" : "") + res);
    181         }
    182         assertEquals("computed and check digest differ", expected1, sb.toString());
    183     }
    184 
    185     public void testfips180_2_multiblock() {
    186 
    187         digest.update(source2.getBytes(), 0, source2.length());
    188 
    189         byte[] computedDigest = digest.digest();
    190 
    191         assertNotNull("computed digest is null", computedDigest);
    192 
    193         StringBuilder sb = new StringBuilder();
    194         for (int i = 0; i < computedDigest.length; i++) {
    195             String res = Integer.toHexString(computedDigest[i] & 0xFF);
    196             sb.append((res.length() == 1 ? "0" : "") + res);
    197         }
    198         assertEquals("computed and check digest differ", expected2, sb.toString());
    199     }
    200 
    201     public void testfips180_2_longMessage() {
    202 
    203         digest.update(source3.getBytes(), 0, source3.length());
    204 
    205         byte[] computedDigest = digest.digest();
    206 
    207         assertNotNull("computed digest is null", computedDigest);
    208 
    209         StringBuilder sb = new StringBuilder();
    210         for (int i = 0; i < computedDigest.length; i++) {
    211             String res = Integer.toHexString(computedDigest[i] & 0xFF);
    212             sb.append((res.length() == 1 ? "0" : "") + res);
    213         }
    214         assertEquals("computed and check digest differ", expected3, sb.toString());
    215     }
    216 }
    217