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