1 /* 2 * Copyright (C) 2016 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 android.keystore.cts; 18 19 import com.google.common.collect.ImmutableSet; 20 21 import com.android.org.bouncycastle.asn1.ASN1Boolean; 22 import com.android.org.bouncycastle.asn1.ASN1Encodable; 23 import com.android.org.bouncycastle.asn1.ASN1Enumerated; 24 import com.android.org.bouncycastle.asn1.ASN1InputStream; 25 import com.android.org.bouncycastle.asn1.ASN1Integer; 26 import com.android.org.bouncycastle.asn1.ASN1OctetString; 27 import com.android.org.bouncycastle.asn1.ASN1Primitive; 28 import com.android.org.bouncycastle.asn1.ASN1Sequence; 29 import com.android.org.bouncycastle.asn1.ASN1Set; 30 import com.android.org.bouncycastle.asn1.DEROctetString; 31 32 import java.io.IOException; 33 import java.io.UnsupportedEncodingException; 34 import java.lang.String; 35 import java.math.BigInteger; 36 import java.security.cert.CertificateParsingException; 37 import java.util.Date; 38 import java.util.Enumeration; 39 import java.util.Set; 40 41 public class Asn1Utils { 42 getIntegerFromAsn1(ASN1Encodable asn1Value)43 public static int getIntegerFromAsn1(ASN1Encodable asn1Value) 44 throws CertificateParsingException { 45 if (asn1Value instanceof ASN1Integer) { 46 return bigIntegerToInt(((ASN1Integer) asn1Value).getValue()); 47 } else if (asn1Value instanceof ASN1Enumerated) { 48 return bigIntegerToInt(((ASN1Enumerated) asn1Value).getValue()); 49 } else { 50 throw new CertificateParsingException( 51 "Integer value expected, " + asn1Value.getClass().getName() + " found."); 52 } 53 } 54 getLongFromAsn1(ASN1Encodable asn1Value)55 public static Long getLongFromAsn1(ASN1Encodable asn1Value) throws CertificateParsingException { 56 if (asn1Value instanceof ASN1Integer) { 57 return bigIntegerToLong(((ASN1Integer) asn1Value).getValue()); 58 } else { 59 throw new CertificateParsingException( 60 "Integer value expected, " + asn1Value.getClass().getName() + " found."); 61 } 62 } 63 getByteArrayFromAsn1(ASN1Encodable asn1Encodable)64 public static byte[] getByteArrayFromAsn1(ASN1Encodable asn1Encodable) 65 throws CertificateParsingException { 66 if (asn1Encodable == null || !(asn1Encodable instanceof DEROctetString)) { 67 throw new CertificateParsingException("Expected DEROctetString"); 68 } 69 ASN1OctetString derOctectString = (ASN1OctetString) asn1Encodable; 70 return derOctectString.getOctets(); 71 } 72 getAsn1EncodableFromBytes(byte[] bytes)73 public static ASN1Encodable getAsn1EncodableFromBytes(byte[] bytes) 74 throws CertificateParsingException { 75 try (ASN1InputStream asn1InputStream = new ASN1InputStream(bytes)) { 76 return asn1InputStream.readObject(); 77 } catch (IOException e) { 78 throw new CertificateParsingException("Failed to parse Encodable", e); 79 } 80 } 81 getAsn1SequenceFromBytes(byte[] bytes)82 public static ASN1Sequence getAsn1SequenceFromBytes(byte[] bytes) 83 throws CertificateParsingException { 84 try (ASN1InputStream asn1InputStream = new ASN1InputStream(bytes)) { 85 return getAsn1SequenceFromStream(asn1InputStream); 86 } catch (IOException e) { 87 throw new CertificateParsingException("Failed to parse SEQUENCE", e); 88 } 89 } 90 getAsn1SequenceFromStream(final ASN1InputStream asn1InputStream)91 public static ASN1Sequence getAsn1SequenceFromStream(final ASN1InputStream asn1InputStream) 92 throws IOException, CertificateParsingException { 93 ASN1Primitive asn1Primitive = asn1InputStream.readObject(); 94 if (!(asn1Primitive instanceof ASN1OctetString)) { 95 throw new CertificateParsingException( 96 "Expected octet stream, found " + asn1Primitive.getClass().getName()); 97 } 98 try (ASN1InputStream seqInputStream = new ASN1InputStream( 99 ((ASN1OctetString) asn1Primitive).getOctets())) { 100 asn1Primitive = seqInputStream.readObject(); 101 if (!(asn1Primitive instanceof ASN1Sequence)) { 102 throw new CertificateParsingException( 103 "Expected sequence, found " + asn1Primitive.getClass().getName()); 104 } 105 return (ASN1Sequence) asn1Primitive; 106 } 107 } 108 getIntegersFromAsn1Set(ASN1Encodable set)109 public static Set<Integer> getIntegersFromAsn1Set(ASN1Encodable set) 110 throws CertificateParsingException { 111 if (!(set instanceof ASN1Set)) { 112 throw new CertificateParsingException( 113 "Expected set, found " + set.getClass().getName()); 114 } 115 116 ImmutableSet.Builder<Integer> builder = ImmutableSet.builder(); 117 for (Enumeration<?> e = ((ASN1Set) set).getObjects(); e.hasMoreElements();) { 118 builder.add(getIntegerFromAsn1((ASN1Integer) e.nextElement())); 119 } 120 return builder.build(); 121 } 122 getStringFromAsn1OctetStreamAssumingUTF8(ASN1Encodable encodable)123 public static String getStringFromAsn1OctetStreamAssumingUTF8(ASN1Encodable encodable) 124 throws CertificateParsingException, UnsupportedEncodingException { 125 if (!(encodable instanceof ASN1OctetString)) { 126 throw new CertificateParsingException( 127 "Expected octet string, found " + encodable.getClass().getName()); 128 } 129 130 ASN1OctetString octetString = (ASN1OctetString) encodable; 131 return new String(octetString.getOctets(), "UTF-8"); 132 } 133 getDateFromAsn1(ASN1Primitive value)134 public static Date getDateFromAsn1(ASN1Primitive value) throws CertificateParsingException { 135 return new Date(getLongFromAsn1(value)); 136 } 137 getBooleanFromAsn1(ASN1Encodable value)138 public static boolean getBooleanFromAsn1(ASN1Encodable value) 139 throws CertificateParsingException { 140 if (!(value instanceof ASN1Boolean)) { 141 throw new CertificateParsingException( 142 "Expected boolean, found " + value.getClass().getName()); 143 } 144 return ((ASN1Boolean) value).isTrue(); 145 } 146 bigIntegerToInt(BigInteger bigInt)147 private static int bigIntegerToInt(BigInteger bigInt) throws CertificateParsingException { 148 if (bigInt.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0 149 || bigInt.compareTo(BigInteger.ZERO) < 0) { 150 throw new CertificateParsingException("INTEGER out of bounds"); 151 } 152 return bigInt.intValue(); 153 } 154 bigIntegerToLong(BigInteger bigInt)155 private static long bigIntegerToLong(BigInteger bigInt) throws CertificateParsingException { 156 if (bigInt.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0 157 || bigInt.compareTo(BigInteger.ZERO) < 0) { 158 throw new CertificateParsingException("INTEGER out of bounds"); 159 } 160 return bigInt.longValue(); 161 } 162 } 163