001/*
002 * Copyright 2017-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2017-2024 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-2024 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.NotNull;
046import com.unboundid.util.Nullable;
047import com.unboundid.util.StaticUtils;
048import com.unboundid.util.ThreadSafety;
049import com.unboundid.util.ThreadSafetyLevel;
050
051
052
053/**
054 * This enum defines a set of reasons for which a CRL distribution point may
055 * revoke a certificate.
056 */
057@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
058public enum CRLDistributionPointRevocationReason
059{
060  /**
061   * Indicates that a CRL distribution point may revoke a certificate for an
062   * unspecified reason.
063   */
064  UNSPECIFIED("unspecified", 0),
065
066
067
068  /**
069   * Indicates that a CRL distribution point may revoke a certificate if the
070   * certificate's private key may have been compromised.
071   */
072  KEY_COMPROMISE("keyCompromise", 1),
073
074
075
076  /**
077   * Indicates that a CRL distribution point may revoke a certificate if the
078   * certificate issuer's private key may have been compromised.
079   */
080  CA_COMPROMISE("caCompromise", 2),
081
082
083
084  /**
085   * Indicates that a CRL distribution point may revoke a certificate if the
086   * owner of a certificate is no longer affiliated with its issuer.
087   */
088  AFFILIATION_CHANGED("affiliationChanged", 3),
089
090
091
092  /**
093   * Indicates that a CRL distribution point may revoke a certificate if it has
094   * been superseded by a newer certificate.
095   */
096  SUPERSEDED("superseded", 4),
097
098
099
100  /**
101   * Indicates that a CRL distribution point may revoke a certificate if the
102   * certification authority is no longer in operation.
103   */
104  CESSATION_OF_OPERATION("cessationOfOperation", 5),
105
106
107
108  /**
109   * Indicates that a CRL distribution point may revoke a certificate if the
110   * certificate has been put on hold.
111   */
112  CERTIFICATE_HOLD("certificateHold", 6),
113
114
115
116  /**
117   * Indicates that a CRL distribution point may revoke a certificate if one
118   * or more of the privileges granted to the certificate have been withdrawn.
119   */
120  PRIVILEGE_WITHDRAWN("privilegeWithdrawn", 7),
121
122
123
124  /**
125   * Indicates that a CRL distribution point may revoke a certificate if an
126   * associated attribute authority has been compromised.
127   */
128  AA_COMPROMISE("aaCompromise", 8);
129
130
131
132  // The position of this revocation reason value in the bit string.
133  private final int bitPosition;
134
135  // A human-readable name for this revocation reason.
136  @NotNull private final String name;
137
138
139
140  /**
141   * Creates a CRL distribution point revocation reason value with the provided
142   * information.
143   *
144   * @param  name         A human-readable name for this revocation reason.
145   * @param  bitPosition  The bit string index of the bit that indicates whether
146   *                      this reason applies.
147   */
148  CRLDistributionPointRevocationReason(@NotNull final String name,
149                                       final int bitPosition)
150  {
151    this.name = name;
152    this.bitPosition = bitPosition;
153  }
154
155
156
157  /**
158   * Retrieves a human-readable name for this CRL distribution point revocation
159   * reason.
160   *
161   * @return  A human-readable name for this CRL distribution point revocation
162   *          reason.
163   */
164  @NotNull()
165  public String getName()
166  {
167    return name;
168  }
169
170
171
172  /**
173   * Retrieves the bit string index of the bit that indicates whether this
174   * reason applies.
175   *
176   * @return  The bit string index of the bit that indicates whether this reason
177   *          applies.
178   */
179  int getBitPosition()
180  {
181    return bitPosition;
182  }
183
184
185
186  /**
187   * Retrieves a set that contains all of the revocation reasons that are set in
188   * the provided bit string.
189   *
190   * @param  bitString  The bit string to examine.
191   *
192   * @return  A set that contains all of the revocation reasons that are set in
193   *          the provided bit string.
194   */
195  @NotNull()
196  static Set<CRLDistributionPointRevocationReason>
197              getReasonSet(@NotNull final ASN1BitString bitString)
198  {
199    final boolean[] bits = bitString.getBits();
200
201    final EnumSet<CRLDistributionPointRevocationReason> s =
202         EnumSet.noneOf(CRLDistributionPointRevocationReason.class);
203    for (final CRLDistributionPointRevocationReason r : values())
204    {
205      if ((bits.length > r.bitPosition) && bits[r.bitPosition])
206      {
207        s.add(r);
208      }
209    }
210
211    return Collections.unmodifiableSet(s);
212  }
213
214
215
216  /**
217   * Encodes the provided set of reasons to a bit string.
218   *
219   * @param  type     The DER to use for the bit string.
220   * @param  reasons  The set of reasons to encode.
221   *
222   * @return  The bit string that represents the encoded set of reasons.
223   */
224  @NotNull()
225  static ASN1BitString toBitString(final byte type,
226              @NotNull final Set<CRLDistributionPointRevocationReason> reasons)
227  {
228    final CRLDistributionPointRevocationReason[] values = values();
229    final boolean[] bits = new boolean[values.length];
230    for (final CRLDistributionPointRevocationReason r : values)
231    {
232      bits[r.bitPosition] = reasons.contains(r);
233    }
234
235    return new ASN1BitString(type, bits);
236  }
237
238
239
240  /**
241   * Retrieves the CRL distribution point revocation reason with the specified
242   * name.
243   *
244   * @param  name  The name of the CRL distribution point revocation reason to
245   *               retrieve.  It must not be {@code null}.
246   *
247   * @return  The requested CRL distribution point revocation reason, or
248   *          {@code null} if no such reason is defined.
249   */
250  @Nullable()
251  public static CRLDistributionPointRevocationReason
252                     forName(@NotNull final String name)
253  {
254    switch (StaticUtils.toLowerCase(name))
255    {
256      case "unspecified":
257        return UNSPECIFIED;
258      case "keycompromise":
259      case "key-compromise":
260      case "key_compromise":
261        return KEY_COMPROMISE;
262      case "cacompromise":
263      case "ca-compromise":
264      case "ca_compromise":
265        return CA_COMPROMISE;
266      case "affiliationchanged":
267      case "affiliation-changed":
268      case "affiliation_changed":
269        return AFFILIATION_CHANGED;
270      case "superseded":
271        return SUPERSEDED;
272      case "cessationofoperation":
273      case "cessation-of-operation":
274      case "cessation_of_operation":
275        return CESSATION_OF_OPERATION;
276      case "certificatehold":
277      case "certificate-hold":
278      case "certificate_hold":
279        return CERTIFICATE_HOLD;
280      case "privilegewithdrawn":
281      case "privilege-withdrawn":
282      case "privilege_withdrawn":
283        return PRIVILEGE_WITHDRAWN;
284      case "aacompromise":
285      case "aa-compromise":
286      case "aa_compromise":
287        return AA_COMPROMISE;
288      default:
289        return null;
290    }
291  }
292}