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 17 package org.conscrypt.ct; 18 19 import java.io.ByteArrayInputStream; 20 import java.io.ByteArrayOutputStream; 21 import java.io.InputStream; 22 import java.io.OutputStream; 23 24 /** 25 * SignedCertificateTimestamp structure, as defined by RFC6962 Section 3.2. 26 */ 27 public class SignedCertificateTimestamp { 28 public enum Version { 29 V1 30 }; 31 32 public enum SignatureType { 33 CERTIFICATE_TIMESTAMP, 34 TREE_HASH 35 }; 36 37 public enum Origin { 38 EMBEDDED, 39 TLS_EXTENSION, 40 OCSP_RESPONSE 41 }; 42 43 private final Version version; 44 private final byte[] logId; 45 private final long timestamp; 46 private final byte[] extensions; 47 private final DigitallySigned signature; 48 49 // origin is implied from the SCT's source and is not encoded in it, 50 // and affects the verification process. 51 private final Origin origin; 52 SignedCertificateTimestamp(Version version, byte[] logId, long timestamp, byte[] extensions, DigitallySigned signature, Origin origin)53 public SignedCertificateTimestamp(Version version, byte[] logId, 54 long timestamp, byte[] extensions, 55 DigitallySigned signature, Origin origin) { 56 this.version = version; 57 this.logId = logId; 58 this.timestamp = timestamp; 59 this.extensions = extensions; 60 this.signature = signature; 61 this.origin = origin; 62 } 63 getVersion()64 public Version getVersion() { 65 return version; 66 } getLogID()67 public byte[] getLogID() { 68 return logId; 69 } getTimestamp()70 public long getTimestamp() { 71 return timestamp; 72 } getExtensions()73 public byte[] getExtensions() { 74 return extensions; 75 } getSignature()76 public DigitallySigned getSignature() { 77 return signature; 78 } getOrigin()79 public Origin getOrigin() { 80 return origin; 81 } 82 83 /** 84 * Decode a TLS encoded SignedCertificateTimestamp structure. 85 */ decode(InputStream input, Origin origin)86 public static SignedCertificateTimestamp decode(InputStream input, Origin origin) 87 throws SerializationException { 88 int version = Serialization.readNumber(input, CTConstants.VERSION_LENGTH); 89 if (version != Version.V1.ordinal()) { 90 throw new SerializationException("Unsupported SCT version " + version); 91 } 92 93 return new SignedCertificateTimestamp( 94 Version.V1, 95 Serialization.readFixedBytes(input, CTConstants.LOGID_LENGTH), 96 Serialization.readLong(input, CTConstants.TIMESTAMP_LENGTH), 97 Serialization.readVariableBytes(input, CTConstants.EXTENSIONS_LENGTH_BYTES), 98 DigitallySigned.decode(input), 99 origin 100 ); 101 } 102 103 /** 104 * Decode a TLS encoded SignedCertificateTimestamp structure. 105 */ decode(byte[] input, Origin origin)106 public static SignedCertificateTimestamp decode(byte[] input, Origin origin) 107 throws SerializationException { 108 return decode(new ByteArrayInputStream(input), origin); 109 } 110 111 /** 112 * TLS encode the signed part of the SCT, as described by RFC6962 section 3.2. 113 */ encodeTBS(OutputStream output, CertificateEntry certEntry)114 public void encodeTBS(OutputStream output, CertificateEntry certEntry) 115 throws SerializationException { 116 Serialization.writeNumber(output, version.ordinal(), CTConstants.VERSION_LENGTH); 117 Serialization.writeNumber(output, SignatureType.CERTIFICATE_TIMESTAMP.ordinal(), 118 CTConstants.SIGNATURE_TYPE_LENGTH); 119 Serialization.writeNumber(output, timestamp, CTConstants.TIMESTAMP_LENGTH); 120 certEntry.encode(output); 121 Serialization.writeVariableBytes(output, extensions, CTConstants.EXTENSIONS_LENGTH_BYTES); 122 } 123 124 /** 125 * TLS encode the signed part of the SCT, as described by RFC6962 section 3.2. 126 */ encodeTBS(CertificateEntry certEntry)127 public byte[] encodeTBS(CertificateEntry certEntry) 128 throws SerializationException { 129 ByteArrayOutputStream output = new ByteArrayOutputStream(); 130 encodeTBS(output, certEntry); 131 return output.toByteArray(); 132 } 133 } 134 135