content: /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You under the Apache License, Version 2.0
   *  (the "License"); you may not use this file except in compliance with
   *  the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  /**
  * @author Alexander Y. Kleymenov
  * @version $Revision$
  */
  
  package android.framework.org.apache.harmony.security_custom.x509;
  
  import java.math.BigInteger;
  import javax.security.auth.x500.X500Principal;
  import android.framework.org.apache.harmony.security_custom.asn1.ASN1BitString;
  import android.framework.org.apache.harmony.security_custom.asn1.ASN1Explicit;
  import android.framework.org.apache.harmony.security_custom.asn1.ASN1Implicit;
  import android.framework.org.apache.harmony.security_custom.asn1.ASN1Integer;
  import android.framework.org.apache.harmony.security_custom.asn1.ASN1Sequence;
  import android.framework.org.apache.harmony.security_custom.asn1.ASN1Type;
  import android.framework.org.apache.harmony.security_custom.asn1.BerInputStream;
  import android.framework.org.apache.harmony.security_custom.asn1.BitString;
  import android.framework.org.apache.harmony.security_custom.x501.Name;
  
  /**
   * The class encapsulates the ASN.1 DER encoding/decoding work
   * with TBSCertificate structure which is the part of X.509 certificate
   * (as specified in RFC 3280 -
   *  Internet X.509 Public Key Infrastructure.
   *  Certificate and Certificate Revocation List (CRL) Profile.
   *  http://www.ietf.org/rfc/rfc3280.txt):
   *
   * <pre>
   *  TBSCertificate  ::=  SEQUENCE  {
   *       version         [0]  EXPLICIT Version DEFAULT v1,
   *       serialNumber         CertificateSerialNumber,
   *       signature            AlgorithmIdentifier,
   *       issuer               Name,
   *       validity             Validity,
   *       subject              Name,
   *       subjectPublicKeyInfo SubjectPublicKeyInfo,
   *       issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
   *                            -- If present, version MUST be v2 or v3
   *       subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
   *                            -- If present, version MUST be v2 or v3
   *       extensions      [3]  EXPLICIT Extensions OPTIONAL
   *                            -- If present, version MUST be v3
   *  }
   * </pre>
   */
  public final class TBSCertificate {
  
      /** the value of version field of the structure */
      private final int version;
      /** the value of serialNumber field of the structure */
      private final BigInteger serialNumber;
      /** the value of signature field of the structure */
      private final AlgorithmIdentifier signature;
      /** the value of issuer field of the structure */
      private final Name issuer;
      /** the value of validity field of the structure */
      private final Validity validity;
      /** the value of subject field of the structure */
      private final Name subject;
      /** the value of subjectPublicKeyInfo field of the structure */
      private final SubjectPublicKeyInfo subjectPublicKeyInfo;
      /** the value of issuerUniqueID field of the structure */
      private final boolean[] issuerUniqueID;
      /** the value of subjectUniqueID field of the structure */
      private final boolean[] subjectUniqueID;
      /** the value of extensions field of the structure */
      private final Extensions extensions;
      /** the ASN.1 encoded form of TBSCertificate */
      private byte[] encoding;
  
      public TBSCertificate(int version, BigInteger serialNumber,
                            AlgorithmIdentifier signature, Name issuer,
                            Validity validity, Name subject,
                            SubjectPublicKeyInfo subjectPublicKeyInfo,
                            boolean[] issuerUniqueID, boolean[] subjectUniqueID,
                            Extensions extensions) {
          this.version = version;
          this.serialNumber = serialNumber;
          this.signature = signature;
          this.issuer = issuer;
          this.validity = validity;
          this.subject = subject;
          this.subjectPublicKeyInfo = subjectPublicKeyInfo;
          this.issuerUniqueID = issuerUniqueID;
          this.subjectUniqueID = subjectUniqueID;
          this.extensions = extensions;
      }
  
      private TBSCertificate(int version, BigInteger serialNumber,
                            AlgorithmIdentifier signature, Name issuer,
                            Validity validity, Name subject,
                            SubjectPublicKeyInfo subjectPublicKeyInfo,
                            boolean[] issuerUniqueID, boolean[] subjectUniqueID,
                            Extensions extensions, byte[] encoding) {
          this(version, serialNumber, signature, issuer, validity, subject,
               subjectPublicKeyInfo, issuerUniqueID, subjectUniqueID, extensions);
          this.encoding = encoding;
      }
  
      /**
       * Returns the value of version field of the structure.
       */
      public int getVersion() {
          return version;
      }
  
      /**
       * Returns the value of serialNumber field of the structure.
       */
      public BigInteger getSerialNumber() {
          return serialNumber;
      }
  
      /**
       * Returns the value of signature field of the structure.
       */
      public AlgorithmIdentifier getSignature() {
          return signature;
      }
  
      /**
       * Returns the value of issuer field of the structure.
       */
      public Name getIssuer() {
          return issuer;
      }
  
      /**
       * Returns the value of validity field of the structure.
       */
      public Validity getValidity() {
          return validity;
      }
  
      /**
       * Returns the value of subject field of the structure.
       */
      public Name getSubject() {
          return subject;
      }
  
      /**
       * Returns the value of subjectPublicKeyInfo field of the structure.
       */
      public SubjectPublicKeyInfo getSubjectPublicKeyInfo() {
          return subjectPublicKeyInfo;
      }
  
      /**
       * Returns the value of issuerUniqueID field of the structure.
       */
      public boolean[] getIssuerUniqueID() {
          return issuerUniqueID;
      }
  
      /**
       * Returns the value of subjectUniqueID field of the structure.
       */
      public boolean[] getSubjectUniqueID() {
          return subjectUniqueID;
      }
  
      /**
       * Returns the value of extensions field of the structure.
       */
      public Extensions getExtensions() {
          return extensions;
      }
  
      /**
       * Returns ASN.1 encoded form of this X.509 TBSCertificate value.
       */
      public byte[] getEncoded() {
          if (encoding == null) {
              encoding = ASN1.encode(this);
          }
          return encoding;
      }
  
      public void dumpValue(StringBuilder sb) {
          sb.append('[');
          sb.append("\n  Version: V").append(version+1);
          sb.append("\n  Subject: ").append(subject.getName(X500Principal.RFC2253));
          sb.append("\n  Signature Algorithm: ");
          signature.dumpValue(sb);
          sb.append("\n  Key: ").append(subjectPublicKeyInfo.getPublicKey().toString());
          sb.append("\n  Validity: [From: ").append(validity.getNotBefore());
          sb.append("\n               To: ").append(validity.getNotAfter()).append(']');
          sb.append("\n  Issuer: ").append(issuer.getName(X500Principal.RFC2253));
          sb.append("\n  Serial Number: ").append(serialNumber);
          if (issuerUniqueID != null) {
              sb.append("\n  Issuer Id: ");
              for (boolean b : issuerUniqueID) {
                  sb.append(b ? '1' : '0');
              }
          }
          if (subjectUniqueID != null) {
              sb.append("\n  Subject Id: ");
              for (boolean b : subjectUniqueID) {
                  sb.append(b ? '1' : '0');
              }
          }
          if (extensions != null) {
              sb.append("\n\n  Extensions: ");
              sb.append("[\n");
              extensions.dumpValue(sb, "    ");
              sb.append("  ]");
          }
          sb.append("\n]");
      }
  
      /**
       * X.509 TBSCertificate encoder/decoder.
       */
      public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
              new ASN1Explicit(0, ASN1Integer.getInstance()), ASN1Integer.getInstance(),
              AlgorithmIdentifier.ASN1, Name.ASN1,
              Validity.ASN1, Name.ASN1, SubjectPublicKeyInfo.ASN1,
              new ASN1Implicit(1, ASN1BitString.getInstance()),
              new ASN1Implicit(2, ASN1BitString.getInstance()),
              new ASN1Explicit(3, Extensions.ASN1)}) {
          {
              setDefault(new byte[] {0}, 0);
              setOptional(7);
              setOptional(8);
              setOptional(9);
          }
  
          @Override protected Object getDecodedObject(BerInputStream in) {
              Object[] values = (Object[]) in.content;
  
              boolean[] issuerUniqueID = (values[7] == null)
                  ? null : ((BitString) values[7]).toBooleanArray();
              boolean[] subjectUniqueID = (values[8] == null)
                  ? null : ((BitString) values[8]).toBooleanArray();
              return new TBSCertificate(
                          ASN1Integer.toIntValue(values[0]),
                          new BigInteger((byte[]) values[1]),
                          (AlgorithmIdentifier) values[2],
                          (Name) values[3],
                          (Validity) values[4],
                          (Name) values[5],
                          (SubjectPublicKeyInfo) values[6],
                          issuerUniqueID,
                          subjectUniqueID,
                          (Extensions) values[9],
                          in.getEncoded()
                      );
          }
  
          @Override protected void getValues(Object object, Object[] values) {
              TBSCertificate tbs = (TBSCertificate) object;
              values[0] = ASN1Integer.fromIntValue(tbs.version);
              values[1] = tbs.serialNumber.toByteArray();
              values[2] = tbs.signature;
              values[3] = tbs.issuer;
              values[4] = tbs.validity;
              values[5] = tbs.subject;
              values[6] = tbs.subjectPublicKeyInfo;
              if (tbs.issuerUniqueID != null) {
                  values[7] = new BitString(tbs.issuerUniqueID);
              }
              if (tbs.subjectUniqueID != null) {
                  values[8] = new BitString(tbs.subjectUniqueID);
              }
              values[9] = tbs.extensions;
          }
      };
  }
  