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