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}