1/* 2 * Copyright (C) 2015 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 17package org.conscrypt.ct; 18 19import junit.framework.TestCase; 20import java.io.ByteArrayOutputStream; 21import java.util.Arrays; 22 23public class SerializationTest extends TestCase { 24 public void test_decode_SignedCertificateTimestamp() throws Exception { 25 byte[] in = new byte[] { 26 0x00, // version 27 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // log id 28 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 29 0x01, 0x02, 0x03, 0x04, // timestamp 30 0x05, 0x06, 0x07, 0x08, 31 0x00, 0x00, // extensions length 32 0x04, 0x03, // hash & signature algorithm 33 0x00, 0x04, // signature length 34 0x12, 0x34, 0x56, 0x78 // signature 35 }; 36 37 SignedCertificateTimestamp sct 38 = SignedCertificateTimestamp.decode(in, SignedCertificateTimestamp.Origin.EMBEDDED); 39 40 assertEquals(SignedCertificateTimestamp.Version.V1, sct.getVersion()); 41 assertEquals(0x0102030405060708L, sct.getTimestamp()); 42 assertEquals(0, sct.getExtensions().length); 43 assertEquals(DigitallySigned.HashAlgorithm.SHA256, 44 sct.getSignature().getHashAlgorithm()); 45 assertEquals(DigitallySigned.SignatureAlgorithm.ECDSA, 46 sct.getSignature().getSignatureAlgorithm()); 47 assertTrue(Arrays.equals(new byte[] { 0x12, 0x34, 0x56, 0x78}, 48 sct.getSignature().getSignature())); 49 assertEquals(SignedCertificateTimestamp.Origin.EMBEDDED, sct.getOrigin()); 50 } 51 52 public void test_decode_invalid_SignedCertificateTimestamp() throws Exception { 53 byte[] sct = new byte[] { 54 0x00, // version 55 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // log id 56 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 57 0x01, 0x02, 0x03, 0x04, // timestamp 58 0x05, 0x06, 0x07, 0x08, 59 0x00, 0x00, // extensions length 60 0x04, 0x03, // hash & signature algorithm 61 0x00, 0x04, // signature length 62 0x12, 0x34, 0x56, 0x78 // signature 63 }; 64 65 // Make sure the original decodes fine 66 SignedCertificateTimestamp.decode(sct, SignedCertificateTimestamp.Origin.EMBEDDED); 67 68 // Perform various modification to it, and make sure it throws an exception on decoding 69 try { 70 byte[] in = sct.clone(); 71 in[0] = 1; // Modify version field 72 SignedCertificateTimestamp.decode(in, SignedCertificateTimestamp.Origin.EMBEDDED); 73 fail("SerializationException not thrown on unsupported version"); 74 } catch (SerializationException e) {} 75 76 try { 77 byte[] in = sct.clone(); 78 in[41] = 1; // Modify extensions lemgth 79 SignedCertificateTimestamp.decode(in, SignedCertificateTimestamp.Origin.EMBEDDED); 80 fail("SerializationException not thrown on invalid extensions length"); 81 } catch (SerializationException e) {} 82 } 83 84 public void test_decode_DigitallySigned() throws Exception { 85 byte[] in = new byte[] { 86 0x04, 0x03, // hash & signature algorithm 87 0x00, 0x04, // signature length 88 0x12, 0x34, 0x56, 0x78 // signature 89 }; 90 91 DigitallySigned dst = DigitallySigned.decode(in); 92 assertEquals(DigitallySigned.HashAlgorithm.SHA256, dst.getHashAlgorithm()); 93 assertEquals(DigitallySigned.SignatureAlgorithm.ECDSA, dst.getSignatureAlgorithm()); 94 assertEqualByteArrays(new byte[] { 0x12, 0x34, 0x56, 0x78}, dst.getSignature()); 95 } 96 97 public void test_decode_invalid_DigitallySigned() throws Exception { 98 try { 99 DigitallySigned.decode(new byte[] { 100 0x07, 0x03, // hash & signature algorithm 101 0x00, 0x04, // signature length 102 0x12, 0x34, 0x56, 0x78 // signature 103 }); 104 fail("SerializationException not thrown on invalid hash type"); 105 } catch (SerializationException e) {} 106 107 try { 108 DigitallySigned.decode(new byte[] { 109 0x04, 0x04, // hash & signature algorithm 110 0x00, 0x04, // signature length 111 0x12, 0x34, 0x56, 0x78 // signature 112 }); 113 fail("SerializationException not thrown on invalid signature type"); 114 } catch (SerializationException e) {} 115 116 try { 117 DigitallySigned.decode(new byte[] { 118 0x07, 0x03, // hash & signature algorithm 119 0x64, 0x35, // signature length 120 0x12, 0x34, 0x56, 0x78 // signature 121 }); 122 fail("SerializationException not thrown on invalid signature length"); 123 } catch (SerializationException e) {} 124 125 try { 126 DigitallySigned.decode(new byte[] { 127 0x07, 0x03, // hash & signature algorithm 128 }); 129 fail("SerializationException not thrown on missing signature"); 130 } catch (SerializationException e) {} 131 } 132 133 public void test_encode_CertificateEntry_X509Certificate() throws Exception { 134 // Use a dummy certificate. It doesn't matter, CertificateEntry doesn't care about the contents. 135 CertificateEntry entry = CertificateEntry.createForX509Certificate(new byte[] { 0x12, 0x34, 0x56, 0x78 }); 136 ByteArrayOutputStream output = new ByteArrayOutputStream(); 137 entry.encode(output); 138 139 assertEqualByteArrays(new byte[] { 140 0x00, 0x00, // entry_type 141 0x00, 0x00, 0x04, // x509_entry length 142 0x12, 0x34, 0x56, 0x78 // x509_entry 143 }, output.toByteArray()); 144 } 145 146 public void test_encode_CertificateEntry_PreCertificate() throws Exception { 147 // Use a dummy certificate and issuer key hash. It doesn't matter, 148 // CertificateEntry doesn't care about the contents. 149 CertificateEntry entry = CertificateEntry.createForPrecertificate(new byte[] { 0x12, 0x34, 0x56, 0x78 }, 150 new byte[32]); 151 152 ByteArrayOutputStream output = new ByteArrayOutputStream(); 153 entry.encode(output); 154 155 assertEqualByteArrays(new byte[] { 156 0x00, 0x01, // entry_type 157 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // issuer key hash 158 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 159 0x00, 0x00, 0x04, // precert_entry length 160 0x12, 0x34, 0x56, 0x78 // precert_entry 161 }, output.toByteArray()); 162 } 163 164 public void test_readDEROctetString() throws Exception { 165 byte[] in, expected; 166 167 in = new byte[] { 168 0x04, // TAG 169 0x06, // length 170 0x01, 0x02, 0x03, 0x04, 0x05, 0x05 // data 171 }; 172 expected = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x05 }; 173 assertEqualByteArrays(expected, Serialization.readDEROctetString(in)); 174 175 in = new byte[203]; 176 in[0] = 0x04; // TAG 177 in[1] = (byte)0x81; // long length flag 178 in[2] = (byte)200; // length 179 in[3] = 0x45; // data, the rest is just zeros 180 181 expected = new byte[200]; 182 expected[0] = 0x45; 183 assertEqualByteArrays(expected, Serialization.readDEROctetString(in)); 184 185 try { 186 in = new byte[] { 187 0x12, // wrong tag 188 0x06, // length 189 0x01, 0x02, 0x03, 0x04, 0x05, 0x05 // data 190 }; 191 Serialization.readDEROctetString(in); 192 fail("SerializationException not thrown on invalid tag."); 193 } catch (SerializationException e) {} 194 195 try { 196 in = new byte[] { 197 0x04, // wrong tag 198 0x06, // length 199 0x01, 0x02 // data 200 }; 201 Serialization.readDEROctetString(in); 202 fail("SerializationException not thrown on invalid length."); 203 } catch (SerializationException e) {} 204 } 205 206 public static void assertEqualByteArrays(byte[] expected, byte[] actual) { 207 assertEquals(Arrays.toString(expected), Arrays.toString(actual)); 208 } 209} 210 211