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}