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