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 com.unboundid.asn1.ASN1BitString;
041import com.unboundid.util.Debug;
042import com.unboundid.util.NotMutable;
043import com.unboundid.util.NotNull;
044import com.unboundid.util.OID;
045import com.unboundid.util.StaticUtils;
046import com.unboundid.util.ThreadSafety;
047import com.unboundid.util.ThreadSafetyLevel;
048
049import static com.unboundid.util.ssl.cert.CertMessages.*;
050
051
052
053/**
054 * This class provides an implementation of the key usage X.509 certificate
055 * extension as described in
056 * <A HREF="https://www.ietf.org/rfc/rfc5280.txt">RFC 5280</A> section 4.2.1.3.
057 * This can be used to determine how the certificate's key is intended to be
058 * used.
059 * <BR><BR>
060 * The OID for this extension is 2.5.29.15 and the value has the following
061 * encoding:
062 * <PRE>
063 *   KeyUsage ::= BIT STRING {
064 *        digitalSignature        (0),
065 *        nonRepudiation          (1), -- recent editions of X.509 have
066 *                             -- renamed this bit to contentCommitment
067 *        keyEncipherment         (2),
068 *        dataEncipherment        (3),
069 *        keyAgreement            (4),
070 *        keyCertSign             (5),
071 *        cRLSign                 (6),
072 *        encipherOnly            (7),
073 *        decipherOnly            (8) }
074 * </PRE>
075 */
076@NotMutable()
077@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
078public final class KeyUsageExtension
079       extends X509CertificateExtension
080{
081  /**
082   * The OID (2.5.29.15) for key usage extensions.
083   */
084  @NotNull public static final OID KEY_USAGE_OID = new OID("2.5.29.15");
085
086
087
088  /**
089   * The serial version UID for this serializable class.
090   */
091  private static final long serialVersionUID = 5453303403925657600L;
092
093
094
095  // Indicates whether the crlSign bit is set.
096  private final boolean crlSign;
097
098  // Indicates whether the dataEncipherment bit is set.
099  private final boolean dataEncipherment;
100
101  // Indicates whether the decipherOnly bit is set.
102  private final boolean decipherOnly;
103
104  // Indicates whether the digitalSignature bit is set.
105  private final boolean digitalSignature;
106
107  // Indicates whether the encipherOnly bit is set.
108  private final boolean encipherOnly;
109
110  // Indicates whether the keyAgreement bit is set.
111  private final boolean keyAgreement;
112
113  // Indicates whether the keyCertSign bit is set.
114  private final boolean keyCertSign;
115
116  // Indicates whether the keyEncipherment bit is set.
117  private final boolean keyEncipherment;
118
119  // Indicates whether the nonRepudiation bit is set.
120  private final boolean nonRepudiation;
121
122
123
124  /**
125   * Creates a new key usage extension with the provided information.
126   *
127   * @param  isCritical        Indicates whether this extension should be
128   *                           considered critical.
129   * @param  digitalSignature  Indicates whether the digitalSignature bit should
130   *                           be set.
131   * @param  nonRepudiation    Indicates whether the nonRepudiation bit should
132   *                           be set.
133   * @param  keyEncipherment   Indicates whether the keyEncipherment bit should
134   *                           be set.
135   * @param  dataEncipherment  Indicates whether the dataEncipherment bit should
136   *                           be set.
137   * @param  keyAgreement      Indicates whether the keyAgreement bit should be
138   *                           set.
139   * @param  keyCertSign       Indicates whether the keyCertSign bit should be
140   *                           set.
141   * @param  crlSign           Indicates whether the crlSign bit should be set.
142   * @param  encipherOnly      Indicates whether the encipherOnly bit should be
143   *                           set.
144   * @param  decipherOnly      Indicates whether the decipherOnly bit should be
145   *                           set.
146   */
147  KeyUsageExtension(final boolean isCritical, final boolean digitalSignature,
148                    final boolean nonRepudiation, final boolean keyEncipherment,
149                    final boolean dataEncipherment, final boolean keyAgreement,
150                    final boolean keyCertSign, final boolean crlSign,
151                    final boolean encipherOnly, final boolean decipherOnly)
152  {
153    super(KEY_USAGE_OID, isCritical,
154         new ASN1BitString(digitalSignature, nonRepudiation, keyEncipherment,
155              dataEncipherment, keyAgreement, keyCertSign, crlSign,
156              encipherOnly, decipherOnly).encode());
157
158    this.digitalSignature = digitalSignature;
159    this.nonRepudiation = nonRepudiation;
160    this.keyEncipherment = keyEncipherment;
161    this.dataEncipherment = dataEncipherment;
162    this.keyAgreement = keyAgreement;
163    this.keyCertSign = keyCertSign;
164    this.crlSign = crlSign;
165    this.encipherOnly = encipherOnly;
166    this.decipherOnly = decipherOnly;
167  }
168
169
170
171  /**
172   * Creates a new key usage extension from the provided generic extension.
173   *
174   * @param  extension  The extension to decode as a key usage extension.
175   *
176   * @throws  CertException  If the provided extension cannot be decoded as a
177   *                         key usage extension.
178   */
179  KeyUsageExtension(@NotNull final X509CertificateExtension extension)
180       throws CertException
181  {
182    super(extension);
183
184    try
185    {
186      final ASN1BitString valueBitString =
187           ASN1BitString.decodeAsBitString(extension.getValue());
188      final boolean[] bits = valueBitString.getBits();
189
190      digitalSignature = ((bits.length > 0) && bits[0]);
191      nonRepudiation = ((bits.length > 1) && bits[1]);
192      keyEncipherment = ((bits.length > 2) && bits[2]);
193      dataEncipherment = ((bits.length > 3) && bits[3]);
194      keyAgreement = ((bits.length > 4) && bits[4]);
195      keyCertSign = ((bits.length > 5) && bits[5]);
196      crlSign = ((bits.length > 6) && bits[6]);
197      encipherOnly = ((bits.length > 7) && bits[7]);
198      decipherOnly = ((bits.length > 8) && bits[8]);
199    }
200    catch (final Exception e)
201    {
202      Debug.debugException(e);
203      throw new CertException(
204           ERR_KEY_USAGE_EXTENSION_CANNOT_PARSE.get(
205                String.valueOf(extension), StaticUtils.getExceptionMessage(e)),
206           e);
207    }
208  }
209
210
211
212  /**
213   * Indicates whether the digital signature bit is set.  If {@code true}, then
214   * the key may be used for verifying digital signatures (other than signatures
215   * on certificates or CRLs, as those usages are covered by the
216   * {@link #isKeyCertSignBitSet()} and {@link #isCRLSignBitSet()} methods,
217   * respectively).
218   *
219   * @return  {@code true} if the digital signature bit is set, or {@code false}
220   *          if not.
221   */
222  public boolean isDigitalSignatureBitSet()
223  {
224    return digitalSignature;
225  }
226
227
228
229  /**
230   * Indicates whether the non-repudiation bit is set.  If {@code true}, then
231   * the key may be used to prevent someone from denying the authenticity of a
232   * digital signature generated with the key.
233   *
234   * @return  {@code true} if the non-repudiation bit is set, or {@code false}
235   *          if not.
236   */
237  public boolean isNonRepudiationBitSet()
238  {
239    return nonRepudiation;
240  }
241
242
243
244  /**
245   * Indicates whether the key encipherment bit is set.  If {@code true}, then
246   * the public key may be used for encrypting other private keys or secret keys
247   * (for example, to protect the keys while they are being transported).
248   *
249   * @return  {@code true} if the key encipherment bit is set, or {@code false}
250   *          if not.
251   */
252  public boolean isKeyEnciphermentBitSet()
253  {
254    return keyEncipherment;
255  }
256
257
258
259  /**
260   * Indicates whether the data encipherment bit is set.  If {@code true}, then
261   * the public key may be used for encrypting arbitrary data without the need
262   * for a symmetric cipher.
263   *
264   * @return  {@code true} if the data encipherment bit is set, or {@code false}
265   *          if not.
266   */
267  public boolean isDataEnciphermentBitSet()
268  {
269    return dataEncipherment;
270  }
271
272
273
274  /**
275   * Indicates whether the key agreement bit is set.  If {@code true}, then
276   * the public key may be used for key agreement processing.
277   *
278   * @return  {@code true} if the key agreement bit is set, or {@code false} if
279   *          not.
280   */
281  public boolean isKeyAgreementBitSet()
282  {
283    return keyAgreement;
284  }
285
286
287
288  /**
289   * Indicates whether the key cert sign bit is set.  If {@code true}, then the
290   * public key may be used for verifying certificate signatures.
291   *
292   * @return  {@code true} if the CRL sign bit is set, or {@code false} if not.
293   */
294  public boolean isKeyCertSignBitSet()
295  {
296    return keyCertSign;
297  }
298
299
300
301  /**
302   * Indicates whether the CRL sign bit is set.  If {@code true}, then the
303   * public key may be used for verifying certificate revocation list (CRL)
304   * signatures.
305   *
306   * @return  {@code true} if the CRL sign bit is set, or {@code false} if not.
307   */
308  public boolean isCRLSignBitSet()
309  {
310    return crlSign;
311  }
312
313
314
315  /**
316   * Indicates whether the encipher only bit is set.  If {@code true}, and if
317   * the {@link #isKeyAgreementBitSet()} is also {@code true}, then the public
318   * key may be used only for enciphering data when performing key agreement.
319   *
320   * @return  {@code true} if the encipher only bit is set, or {@code false} if
321   *          not.
322   */
323  public boolean isEncipherOnlyBitSet()
324  {
325    return encipherOnly;
326  }
327
328
329
330  /**
331   * Indicates whether the decipher only bit is set.  If {@code true}, and if
332   * the {@link #isKeyAgreementBitSet()} is also {@code true}, then the public
333   * key may be used only for deciphering data when performing key agreement.
334   *
335   * @return  {@code true} if the decipher only bit is set, or {@code false} if
336   *          not.
337   */
338  public boolean isDecipherOnlyBitSet()
339  {
340    return decipherOnly;
341  }
342
343
344
345  /**
346   * {@inheritDoc}
347   */
348  @Override()
349  @NotNull()
350  public String getExtensionName()
351  {
352    return INFO_KEY_USAGE_EXTENSION_NAME.get();
353  }
354
355
356
357  /**
358   * {@inheritDoc}
359   */
360  @Override()
361  public void toString(@NotNull final StringBuilder buffer)
362  {
363    buffer.append("KeyUsageExtension(oid='");
364    buffer.append(getOID());
365    buffer.append("', isCritical=");
366    buffer.append(isCritical());
367    buffer.append(", digitalSignature=");
368    buffer.append(digitalSignature);
369    buffer.append(", nonRepudiation=");
370    buffer.append(nonRepudiation);
371    buffer.append(", keyEncipherment=");
372    buffer.append(keyEncipherment);
373    buffer.append(", dataEncipherment=");
374    buffer.append(dataEncipherment);
375    buffer.append(", keyAgreement=");
376    buffer.append(keyAgreement);
377    buffer.append(", keyCertSign=");
378    buffer.append(keyCertSign);
379    buffer.append(", clrSign=");
380    buffer.append(crlSign);
381    buffer.append(", encipherOnly=");
382    buffer.append(encipherOnly);
383    buffer.append(", decipherOnly=");
384    buffer.append(decipherOnly);
385    buffer.append(')');
386  }
387}