Home | History | Annotate | Download | only in x509
      1 package org.bouncycastle.asn1.x509;
      2 
      3 import java.math.BigInteger;
      4 
      5 import org.bouncycastle.asn1.ASN1EncodableVector;
      6 import org.bouncycastle.asn1.ASN1Integer;
      7 import org.bouncycastle.asn1.ASN1Object;
      8 import org.bouncycastle.asn1.ASN1Primitive;
      9 import org.bouncycastle.asn1.ASN1Sequence;
     10 import org.bouncycastle.asn1.ASN1TaggedObject;
     11 import org.bouncycastle.asn1.DERSequence;
     12 import org.bouncycastle.asn1.DERTaggedObject;
     13 
     14 /**
     15  * Class for containing a restriction object subtrees in NameConstraints. See
     16  * RFC 3280.
     17  *
     18  * <pre>
     19  *
     20  *       GeneralSubtree ::= SEQUENCE
     21  *       {
     22  *         base                    GeneralName,
     23  *         minimum         [0]     BaseDistance DEFAULT 0,
     24  *         maximum         [1]     BaseDistance OPTIONAL
     25  *       }
     26  * </pre>
     27  *
     28  * @see org.bouncycastle.asn1.x509.NameConstraints
     29  *
     30  */
     31 public class GeneralSubtree
     32     extends ASN1Object
     33 {
     34     private static final BigInteger ZERO = BigInteger.valueOf(0);
     35 
     36     private GeneralName base;
     37 
     38     private ASN1Integer minimum;
     39 
     40     private ASN1Integer maximum;
     41 
     42     private GeneralSubtree(
     43         ASN1Sequence seq)
     44     {
     45         base = GeneralName.getInstance(seq.getObjectAt(0));
     46 
     47         switch (seq.size())
     48         {
     49         case 1:
     50             break;
     51         case 2:
     52             ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
     53             switch (o.getTagNo())
     54             {
     55             case 0:
     56                 minimum = ASN1Integer.getInstance(o, false);
     57                 break;
     58             case 1:
     59                 maximum = ASN1Integer.getInstance(o, false);
     60                 break;
     61             default:
     62                 throw new IllegalArgumentException("Bad tag number: "
     63                         + o.getTagNo());
     64             }
     65             break;
     66         case 3:
     67         {
     68             {
     69                 ASN1TaggedObject oMin = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
     70                 if (oMin.getTagNo() != 0)
     71                 {
     72                     throw new IllegalArgumentException("Bad tag number for 'minimum': " + oMin.getTagNo());
     73                 }
     74                 minimum = ASN1Integer.getInstance(oMin, false);
     75             }
     76 
     77             {
     78                 ASN1TaggedObject oMax = ASN1TaggedObject.getInstance(seq.getObjectAt(2));
     79                 if (oMax.getTagNo() != 1)
     80                 {
     81                     throw new IllegalArgumentException("Bad tag number for 'maximum': " + oMax.getTagNo());
     82                 }
     83                 maximum = ASN1Integer.getInstance(oMax, false);
     84             }
     85 
     86             break;
     87         }
     88         default:
     89             throw new IllegalArgumentException("Bad sequence size: "
     90                     + seq.size());
     91         }
     92     }
     93 
     94     /**
     95      * Constructor from a given details.
     96      *
     97      * According RFC 3280, the minimum and maximum fields are not used with any
     98      * name forms, thus minimum MUST be zero, and maximum MUST be absent.
     99      * <p>
    100      * If minimum is <code>null</code>, zero is assumed, if
    101      * maximum is <code>null</code>, maximum is absent.
    102      *
    103      * @param base
    104      *            A restriction.
    105      * @param minimum
    106      *            Minimum
    107      *
    108      * @param maximum
    109      *            Maximum
    110      */
    111     public GeneralSubtree(
    112         GeneralName base,
    113         BigInteger minimum,
    114         BigInteger maximum)
    115     {
    116         this.base = base;
    117         if (maximum != null)
    118         {
    119             this.maximum = new ASN1Integer(maximum);
    120         }
    121         if (minimum == null)
    122         {
    123             this.minimum = null;
    124         }
    125         else
    126         {
    127             this.minimum = new ASN1Integer(minimum);
    128         }
    129     }
    130 
    131     public GeneralSubtree(GeneralName base)
    132     {
    133         this(base, null, null);
    134     }
    135 
    136     public static GeneralSubtree getInstance(
    137         ASN1TaggedObject o,
    138         boolean explicit)
    139     {
    140         return new GeneralSubtree(ASN1Sequence.getInstance(o, explicit));
    141     }
    142 
    143     public static GeneralSubtree getInstance(
    144         Object obj)
    145     {
    146         if (obj == null)
    147         {
    148             return null;
    149         }
    150 
    151         if (obj instanceof GeneralSubtree)
    152         {
    153             return (GeneralSubtree) obj;
    154         }
    155 
    156         return new GeneralSubtree(ASN1Sequence.getInstance(obj));
    157     }
    158 
    159     public GeneralName getBase()
    160     {
    161         return base;
    162     }
    163 
    164     public BigInteger getMinimum()
    165     {
    166         if (minimum == null)
    167         {
    168             return ZERO;
    169         }
    170 
    171         return minimum.getValue();
    172     }
    173 
    174     public BigInteger getMaximum()
    175     {
    176         if (maximum == null)
    177         {
    178             return null;
    179         }
    180 
    181         return maximum.getValue();
    182     }
    183 
    184     /**
    185      * Produce an object suitable for an ASN1OutputStream.
    186      *
    187      * Returns:
    188      *
    189      * <pre>
    190      *       GeneralSubtree ::= SEQUENCE
    191      *       {
    192      *         base                    GeneralName,
    193      *         minimum         [0]     BaseDistance DEFAULT 0,
    194      *         maximum         [1]     BaseDistance OPTIONAL
    195      *       }
    196      * </pre>
    197      *
    198      * @return a ASN1Primitive
    199      */
    200     public ASN1Primitive toASN1Primitive()
    201     {
    202         ASN1EncodableVector v = new ASN1EncodableVector();
    203 
    204         v.add(base);
    205 
    206         if (minimum != null && !minimum.getValue().equals(ZERO))
    207         {
    208             v.add(new DERTaggedObject(false, 0, minimum));
    209         }
    210 
    211         if (maximum != null)
    212         {
    213             v.add(new DERTaggedObject(false, 1, maximum));
    214         }
    215 
    216         return new DERSequence(v);
    217     }
    218 }
    219