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.math.BigInteger; 34 import java.security.cert.CertificateParsingException; 35 import java.util.Date; 36 import java.util.Enumeration; 37 import java.util.Set; 38 39 public class Asn1Utils { 40 getIntegerFromAsn1(ASN1Encodable asn1Value)41 public static int getIntegerFromAsn1(ASN1Encodable asn1Value) 42 throws CertificateParsingException { 43 if (asn1Value instanceof ASN1Integer) { 44 return bigIntegerToInt(((ASN1Integer) asn1Value).getValue()); 45 } else if (asn1Value instanceof ASN1Enumerated) { 46 return bigIntegerToInt(((ASN1Enumerated) asn1Value).getValue()); 47 } else { 48 throw new CertificateParsingException( 49 "Integer value expected, " + asn1Value.getClass().getName() + " found."); 50 } 51 } 52 getLongFromAsn1(ASN1Encodable asn1Value)53 public static Long getLongFromAsn1(ASN1Encodable asn1Value) throws CertificateParsingException { 54 if (asn1Value instanceof ASN1Integer) { 55 return bigIntegerToLong(((ASN1Integer) asn1Value).getValue()); 56 } else { 57 throw new CertificateParsingException( 58 "Integer value expected, " + asn1Value.getClass().getName() + " found."); 59 } 60 } 61 getByteArrayFromAsn1(ASN1Encodable asn1Encodable)62 public static byte[] getByteArrayFromAsn1(ASN1Encodable asn1Encodable) 63 throws CertificateParsingException { 64 if (asn1Encodable == null || !(asn1Encodable instanceof DEROctetString)) { 65 throw new CertificateParsingException("Expected DEROctetString"); 66 } 67 ASN1OctetString derOctectString = (ASN1OctetString) asn1Encodable; 68 return derOctectString.getOctets(); 69 } 70 getAsn1SequenceFromBytes(byte[] bytes)71 public static ASN1Sequence getAsn1SequenceFromBytes(byte[] bytes) 72 throws CertificateParsingException { 73 try (ASN1InputStream asn1InputStream = new ASN1InputStream(bytes)) { 74 return getAsn1SequenceFromStream(asn1InputStream); 75 } catch (IOException e) { 76 throw new CertificateParsingException("Failed to parse SEQUENCE", e); 77 } 78 } 79 getAsn1SequenceFromStream(final ASN1InputStream asn1InputStream)80 public static ASN1Sequence getAsn1SequenceFromStream(final ASN1InputStream asn1InputStream) 81 throws IOException, CertificateParsingException { 82 ASN1Primitive asn1Primitive = asn1InputStream.readObject(); 83 if (!(asn1Primitive instanceof ASN1OctetString)) { 84 throw new CertificateParsingException( 85 "Expected octet stream, found " + asn1Primitive.getClass().getName()); 86 } 87 try (ASN1InputStream seqInputStream = new ASN1InputStream( 88 ((ASN1OctetString) asn1Primitive).getOctets())) { 89 asn1Primitive = seqInputStream.readObject(); 90 if (!(asn1Primitive instanceof ASN1Sequence)) { 91 throw new CertificateParsingException( 92 "Expected sequence, found " + asn1Primitive.getClass().getName()); 93 } 94 return (ASN1Sequence) asn1Primitive; 95 } 96 } 97 getIntegersFromAsn1Set(ASN1Encodable set)98 public static Set<Integer> getIntegersFromAsn1Set(ASN1Encodable set) 99 throws CertificateParsingException { 100 if (!(set instanceof ASN1Set)) { 101 throw new CertificateParsingException( 102 "Expected set, found " + set.getClass().getName()); 103 } 104 105 ImmutableSet.Builder<Integer> builder = ImmutableSet.builder(); 106 for (Enumeration<?> e = ((ASN1Set) set).getObjects(); e.hasMoreElements();) { 107 builder.add(getIntegerFromAsn1((ASN1Integer) e.nextElement())); 108 } 109 return builder.build(); 110 } 111 getDateFromAsn1(ASN1Primitive value)112 public static Date getDateFromAsn1(ASN1Primitive value) throws CertificateParsingException { 113 return new Date(getLongFromAsn1(value)); 114 } 115 getBooleanFromAsn1(ASN1Encodable value)116 public static boolean getBooleanFromAsn1(ASN1Encodable value) 117 throws CertificateParsingException { 118 if (!(value instanceof ASN1Boolean)) { 119 throw new CertificateParsingException( 120 "Expected boolean, found " + value.getClass().getName()); 121 } 122 return ((ASN1Boolean) value).isTrue(); 123 } 124 bigIntegerToInt(BigInteger bigInt)125 private static int bigIntegerToInt(BigInteger bigInt) throws CertificateParsingException { 126 if (bigInt.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0 127 || bigInt.compareTo(BigInteger.ZERO) < 0) { 128 throw new CertificateParsingException("INTEGER out of bounds"); 129 } 130 return bigInt.intValue(); 131 } 132 bigIntegerToLong(BigInteger bigInt)133 private static long bigIntegerToLong(BigInteger bigInt) throws CertificateParsingException { 134 if (bigInt.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0 135 || bigInt.compareTo(BigInteger.ZERO) < 0) { 136 throw new CertificateParsingException("INTEGER out of bounds"); 137 } 138 return bigInt.longValue(); 139 } 140 } 141