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}