001/*
002 * Copyright 2017-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2017-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.util.ssl.cert;
022
023
024
025import java.util.Collections;
026import java.util.EnumSet;
027import java.util.Set;
028
029import com.unboundid.asn1.ASN1BitString;
030import com.unboundid.util.StaticUtils;
031import com.unboundid.util.ThreadSafety;
032import com.unboundid.util.ThreadSafetyLevel;
033
034
035
036/**
037 * This enum defines a set of reasons for which a CRL distribution point may
038 * revoke a certificate.
039 */
040@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
041public enum CRLDistributionPointRevocationReason
042{
043  /**
044   * Indicates that a CRL distribution point may revoke a certificate for an
045   * unspecified reason.
046   */
047  UNSPECIFIED("unspecified", 0),
048
049
050
051  /**
052   * Indicates that a CRL distribution point may revoke a certificate if the
053   * certificate's private key may have been compromised.
054   */
055  KEY_COMPROMISE("keyCompromise", 1),
056
057
058
059  /**
060   * Indicates that a CRL distribution point may revoke a certificate if the
061   * certificate issuer's private key may have been compromised.
062   */
063  CA_COMPROMISE("caCompromise", 2),
064
065
066
067  /**
068   * Indicates that a CRL distribution point may revoke a certificate if the
069   * owner of a certificate is no longer affiliated with its issuer.
070   */
071  AFFILIATION_CHANGED("affiliationChanged", 3),
072
073
074
075  /**
076   * Indicates that a CRL distribution point may revoke a certificate if it has
077   * been superseded by a newer certificate.
078   */
079  SUPERSEDED("superseded", 4),
080
081
082
083  /**
084   * Indicates that a CRL distribution point may revoke a certificate if the
085   * certification authority is no longer in operation.
086   */
087  CESSATION_OF_OPERATION("cessationOfOperation", 5),
088
089
090
091  /**
092   * Indicates that a CRL distribution point may revoke a certificate if the
093   * certificate has been put on hold.
094   */
095  CERTIFICATE_HOLD("certificateHold", 6),
096
097
098
099  /**
100   * Indicates that a CRL distribution point may revoke a certificate if one
101   * or more of the privileges granted to the certificate have been withdrawn.
102   */
103  PRIVILEGE_WITHDRAWN("privilegeWithdrawn", 7),
104
105
106
107  /**
108   * Indicates that a CRL distribution point may revoke a certificate if an
109   * associated attribute authority has been compromised.
110   */
111  AA_COMPROMISE("aaCompromise", 8);
112
113
114
115  // The position of this revocation reason value in the bit string.
116  private final int bitPosition;
117
118  // A human-readable name for this revocation reason.
119  private final String name;
120
121
122
123  /**
124   * Creates a CRL distribution point revocation reason value with the provided
125   * information.
126   *
127   * @param  name         A human-readable name for this revocation reason.
128   * @param  bitPosition  The bit string index of the bit that indicates whether
129   *                      this reason applies.
130   */
131  CRLDistributionPointRevocationReason(final String name,
132                                       final int bitPosition)
133  {
134    this.name = name;
135    this.bitPosition = bitPosition;
136  }
137
138
139
140  /**
141   * Retrieves a human-readable name for this CRL distribution point revocation
142   * reason.
143   *
144   * @return  A human-readable name for this CRL distribution point revocation
145   *          reason.
146   */
147  public String getName()
148  {
149    return name;
150  }
151
152
153
154  /**
155   * Retrieves the bit string index of the bit that indicates whether this
156   * reason applies.
157   *
158   * @return  The bit string index of the bit that indicates whether this reason
159   *          applies.
160   */
161  int getBitPosition()
162  {
163    return bitPosition;
164  }
165
166
167
168  /**
169   * Retrieves a set that contains all of the revocation reasons that are set in
170   * the provided bit string.
171   *
172   * @param  bitString  The bit string to examine.
173   *
174   * @return  A set that contains all of the revocation reasons that are set in
175   *          the provided bit string.
176   */
177  static Set<CRLDistributionPointRevocationReason>
178              getReasonSet(final ASN1BitString bitString)
179  {
180    final boolean[] bits = bitString.getBits();
181
182    final EnumSet<CRLDistributionPointRevocationReason> s =
183         EnumSet.noneOf(CRLDistributionPointRevocationReason.class);
184    for (final CRLDistributionPointRevocationReason r : values())
185    {
186      if ((bits.length > r.bitPosition) && bits[r.bitPosition])
187      {
188        s.add(r);
189      }
190    }
191
192    return Collections.unmodifiableSet(s);
193  }
194
195
196
197  /**
198   * Encodes the provided set of reasons to a bit string.
199   *
200   * @param  type     The DER to use for the bit string.
201   * @param  reasons  The set of reasons to encode.
202   *
203   * @return  The bit string that represents the encoded set of reasons.
204   */
205  static ASN1BitString toBitString(final byte type,
206              final Set<CRLDistributionPointRevocationReason> reasons)
207  {
208    final CRLDistributionPointRevocationReason[] values = values();
209    final boolean[] bits = new boolean[values.length];
210    for (final CRLDistributionPointRevocationReason r : values)
211    {
212      bits[r.bitPosition] = reasons.contains(r);
213    }
214
215    return new ASN1BitString(type, bits);
216  }
217
218
219
220  /**
221   * Retrieves the CRL distribution point revocation reason with the specified
222   * name.
223   *
224   * @param  name  The name of the CRL distribution point revocation reason to
225   *               retrieve.  It must not be {@code null}.
226   *
227   * @return  The requested CRL distribution point revocation reason, or
228   *          {@code null} if no such reason is defined.
229   */
230  public static CRLDistributionPointRevocationReason forName(final String name)
231  {
232    switch (StaticUtils.toLowerCase(name))
233    {
234      case "unspecified":
235        return UNSPECIFIED;
236      case "keycompromise":
237      case "key-compromise":
238      case "key_compromise":
239        return KEY_COMPROMISE;
240      case "cacompromise":
241      case "ca-compromise":
242      case "ca_compromise":
243        return CA_COMPROMISE;
244      case "affiliationchanged":
245      case "affiliation-changed":
246      case "affiliation_changed":
247        return AFFILIATION_CHANGED;
248      case "superseded":
249        return SUPERSEDED;
250      case "cessationofoperation":
251      case "cessation-of-operation":
252      case "cessation_of_operation":
253        return CESSATION_OF_OPERATION;
254      case "certificatehold":
255      case "certificate-hold":
256      case "certificate_hold":
257        return CERTIFICATE_HOLD;
258      case "privilegewithdrawn":
259      case "privilege-withdrawn":
260      case "privilege_withdrawn":
261        return PRIVILEGE_WITHDRAWN;
262      case "aacompromise":
263      case "aa-compromise":
264      case "aa_compromise":
265        return AA_COMPROMISE;
266      default:
267        return null;
268    }
269  }
270}