diff --git a/.hgtags b/.hgtags index a48294ba6ceaf335fd75eae4b1186e3812707aa7..e774b097c5e65c5aa6852023a73930bc82c4f921 100644 --- a/.hgtags +++ b/.hgtags @@ -194,3 +194,4 @@ a8012d8d7e9c5035de0bdd4887dc9f7c54008f21 jdk8-b69 a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 2a5af0f766d0acd68a81fb08fe11fd66795f86af jdk8-b71 32a57e645e012a1f0665c075969ca598e0dbb948 jdk8-b72 +733885f57e14cc27f5a5ff0dffe641d2fa3c704a jdk8-b73 diff --git a/make/common/Release.gmk b/make/common/Release.gmk index dc43ecf95ea87137feb1ef9030b6ef03f2ebd35e..367eab8fa7ebe669279ccfc5eee382832e14fda3 100644 --- a/make/common/Release.gmk +++ b/make/common/Release.gmk @@ -375,6 +375,7 @@ TOOLS = \ com/sun/tools/javadoc \ com/sun/tools/javah \ com/sun/tools/javap \ + com/sun/tools/jdeps \ com/sun/tools/corba \ com/sun/tools/internal/xjc \ com/sun/tools/internal/ws \ @@ -457,6 +458,7 @@ NOTJRETOOLS = \ javadoc$(EXE_SUFFIX) \ javah$(EXE_SUFFIX) \ javap$(EXE_SUFFIX) \ + jdeps$(EXE_SUFFIX) \ jcmd$(EXE_SUFFIX) \ jdb$(EXE_SUFFIX) \ jps$(EXE_SUFFIX) \ @@ -564,6 +566,7 @@ $(NOT_RT_JAR_LIST): FRC $(ECHO) "sun/tools/javac/" >> $@ $(ECHO) "com/sun/tools/classfile/" >> $@ $(ECHO) "com/sun/tools/javap/" >> $@ + $(ECHO) "com/sun/tools/jdeps/" >> $@ $(ECHO) "sun/tools/jcmd/" >> $@ $(ECHO) "sun/tools/jconsole/" >> $@ $(ECHO) "sun/tools/jps/" >> $@ diff --git a/make/docs/NON_CORE_PKGS.gmk b/make/docs/NON_CORE_PKGS.gmk index b299938e844ca8e7c6cd2e6c70d9adfaf9869df7..949637cfedac1076cb856b528f5d5bee25731066 100644 --- a/make/docs/NON_CORE_PKGS.gmk +++ b/make/docs/NON_CORE_PKGS.gmk @@ -76,7 +76,7 @@ ATTACH_PKGS = com.sun.tools.attach \ JCONSOLE_PKGS = com.sun.tools.jconsole -TREEAPI_PKGS = com.sunsource.doctree \ +TREEAPI_PKGS = com.sun.source.doctree \ com.sun.source.tree \ com.sun.source.util diff --git a/make/launchers/Makefile b/make/launchers/Makefile index 3d9511408b0766b71f4116a7346f8874d3ed9dab..be16512e478a69920406fb607f0fc2b20a65b5cc 100644 --- a/make/launchers/Makefile +++ b/make/launchers/Makefile @@ -63,6 +63,7 @@ $(call make-launcher, javac, com.sun.tools.javac.Main, , ) $(call make-launcher, javadoc, com.sun.tools.javadoc.Main, , ) $(call make-launcher, javah, com.sun.tools.javah.Main, , ) $(call make-launcher, javap, com.sun.tools.javap.Main, , ) +$(call make-launcher, jdeps, com.sun.tools.jdeps.Main, , ) $(call make-launcher, jcmd, sun.tools.jcmd.JCmd, , ) $(call make-launcher, jconsole, sun.tools.jconsole.JConsole, \ -J-Djconsole.showOutputViewer, ) diff --git a/make/launchers/Makefile.launcher b/make/launchers/Makefile.launcher index 1b3e51b6de84998b1ca9c3bf3f315318f5fbd7b1..bb06f80f7cc443b4f1ac9b9ea43b948b07186fcd 100644 --- a/make/launchers/Makefile.launcher +++ b/make/launchers/Makefile.launcher @@ -62,6 +62,10 @@ ifeq ($(PROGRAM),javap) WILDCARDS=true NEVER_ACT_AS_SERVER_CLASS_MACHINE=true endif +ifeq ($(PROGRAM),jdeps) + WILDCARDS=true + NEVER_ACT_AS_SERVER_CLASS_MACHINE=true +endif ifeq ($(PROGRAM),javah) WILDCARDS=true NEVER_ACT_AS_SERVER_CLASS_MACHINE=true diff --git a/makefiles/CompileLaunchers.gmk b/makefiles/CompileLaunchers.gmk index 7a6353426902335a1c7927ca3805cc4bdaa26e27..354fea12044a87404d7d93f96974acc30e47d2cf 100644 --- a/makefiles/CompileLaunchers.gmk +++ b/makefiles/CompileLaunchers.gmk @@ -270,6 +270,11 @@ $(eval $(call SetupLauncher,javap,\ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.javap.Main"$(COMMA) }')) +$(eval $(call SetupLauncher,jdeps,\ + -DEXPAND_CLASSPATH_WILDCARDS \ + -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \ + -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.jdeps.Main"$(COMMA) }')) + BUILD_LAUNCHER_jconsole_CFLAGS_windows:=-DJAVAW BUILD_LAUNCHER_jconsole_LDFLAGS_windows:=user32.lib diff --git a/makefiles/CreateJars.gmk b/makefiles/CreateJars.gmk index 1f7096adf197047f58a0399337cfead22e318829..6250dd83fe20939516e949b478fa04fbf3be096d 100644 --- a/makefiles/CreateJars.gmk +++ b/makefiles/CreateJars.gmk @@ -747,6 +747,7 @@ TOOLS_JAR_INCLUDES := \ com/sun/tools/javadoc \ com/sun/tools/javah \ com/sun/tools/javap \ + com/sun/tools/jdeps \ com/sun/tools/jdi \ com/sun/tools/script/shell \ com/sun/xml/internal/dtdparser \ diff --git a/makefiles/Images.gmk b/makefiles/Images.gmk index 13a6d87f47365f0999cc9b7c56e3d209e08b97e5..53ea58d68ae97351d2e1d5c5bc7e5508ea16f85c 100644 --- a/makefiles/Images.gmk +++ b/makefiles/Images.gmk @@ -103,6 +103,7 @@ NOT_JRE_BIN_FILES := \ javadoc$(EXE_SUFFIX) \ javah$(EXE_SUFFIX) \ javap$(EXE_SUFFIX) \ + jdeps$(EXE_SUFFIX) \ jcmd$(EXE_SUFFIX) \ jdb$(EXE_SUFFIX) \ jps$(EXE_SUFFIX) \ diff --git a/src/share/classes/com/sun/crypto/provider/AESCipher.java b/src/share/classes/com/sun/crypto/provider/AESCipher.java index 0ae68957c43b86d46ffd7822433bce2b3af71773..32cb3e39d3dfecda66dd43b930d9afde52ef2865 100644 --- a/src/share/classes/com/sun/crypto/provider/AESCipher.java +++ b/src/share/classes/com/sun/crypto/provider/AESCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.security.spec.*; import javax.crypto.*; import javax.crypto.spec.*; import javax.crypto.BadPaddingException; +import java.nio.ByteBuffer; /** * This class implements the AES algorithm in its various modes @@ -127,6 +128,21 @@ abstract class AESCipher extends CipherSpi { super(32, "CFB", "NOPADDING"); } } + public static final class AES128_GCM_NoPadding extends OidImpl { + public AES128_GCM_NoPadding() { + super(16, "GCM", "NOPADDING"); + } + } + public static final class AES192_GCM_NoPadding extends OidImpl { + public AES192_GCM_NoPadding() { + super(24, "GCM", "NOPADDING"); + } + } + public static final class AES256_GCM_NoPadding extends OidImpl { + public AES256_GCM_NoPadding() { + super(32, "GCM", "NOPADDING"); + } + } // utility method used by AESCipher and AESWrapCipher static final void checkKeySize(Key key, int fixedKeySize) @@ -531,4 +547,79 @@ abstract class AESCipher extends CipherSpi { return core.unwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType); } + + /** + * Continues a multi-part update of the Additional Authentication + * Data (AAD), using a subset of the provided buffer. + *
+ * Calls to this method provide AAD to the cipher when operating in + * modes such as AEAD (GCM/CCM). If this cipher is operating in + * either GCM or CCM mode, all AAD must be supplied before beginning + * operations on the ciphertext (via the {@code update} and {@code + * doFinal} methods). + * + * @param src the buffer containing the AAD + * @param offset the offset in {@code src} where the AAD input starts + * @param len the number of AAD bytes + * + * @throws IllegalStateException if this cipher is in a wrong state + * (e.g., has not been initialized), does not accept AAD, or if + * operating in either GCM or CCM mode and one of the {@code update} + * methods has already been called for the active + * encryption/decryption operation + * @throws UnsupportedOperationException if this method + * has not been overridden by an implementation + * + * @since 1.8 + */ + @Override + protected void engineUpdateAAD(byte[] src, int offset, int len) { + core.updateAAD(src, offset, len); + } + + /** + * Continues a multi-part update of the Additional Authentication + * Data (AAD). + *
+ * Calls to this method provide AAD to the cipher when operating in + * modes such as AEAD (GCM/CCM). If this cipher is operating in + * either GCM or CCM mode, all AAD must be supplied before beginning + * operations on the ciphertext (via the {@code update} and {@code + * doFinal} methods). + *
+ * All {@code src.remaining()} bytes starting at
+ * {@code src.position()} are processed.
+ * Upon return, the input buffer's position will be equal
+ * to its limit; its limit will not have changed.
+ *
+ * @param src the buffer containing the AAD
+ *
+ * @throws IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized), does not accept AAD, or if
+ * operating in either GCM or CCM mode and one of the {@code update}
+ * methods has already been called for the active
+ * encryption/decryption operation
+ * @throws UnsupportedOperationException if this method
+ * has not been overridden by an implementation
+ *
+ * @since 1.8
+ */
+ @Override
+ protected void engineUpdateAAD(ByteBuffer src) {
+ if (src != null) {
+ int aadLen = src.limit() - src.position();
+ if (aadLen != 0) {
+ if (src.hasArray()) {
+ int aadOfs = src.arrayOffset() + src.position();
+ core.updateAAD(src.array(), aadOfs, aadLen);
+ src.position(src.limit());
+ } else {
+ byte[] aad = new byte[aadLen];
+ src.get(aad);
+ core.updateAAD(aad, 0, aadLen);
+ }
+ }
+ }
+ }
}
+
diff --git a/src/share/classes/com/sun/crypto/provider/AESKeyGenerator.java b/src/share/classes/com/sun/crypto/provider/AESKeyGenerator.java
index 8d8145c0247e2efb825e2d97ab6c7de631a837b2..c58d52b55f302b40783314c40768c7a04eb1f33c 100644
--- a/src/share/classes/com/sun/crypto/provider/AESKeyGenerator.java
+++ b/src/share/classes/com/sun/crypto/provider/AESKeyGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -106,7 +106,7 @@ public final class AESKeyGenerator extends KeyGeneratorSpi {
SecretKeySpec aesKey = null;
if (this.random == null) {
- this.random = SunJCE.RANDOM;
+ this.random = SunJCE.getRandom();
}
byte[] keyBytes = new byte[keySize];
diff --git a/src/share/classes/com/sun/crypto/provider/BlowfishKeyGenerator.java b/src/share/classes/com/sun/crypto/provider/BlowfishKeyGenerator.java
index be747cbe01c9b5a74cfffbc13efaa18cc16c32f8..ceadbe339de48b675108df9a43bdf7599751d537 100644
--- a/src/share/classes/com/sun/crypto/provider/BlowfishKeyGenerator.java
+++ b/src/share/classes/com/sun/crypto/provider/BlowfishKeyGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -104,7 +104,7 @@ public final class BlowfishKeyGenerator extends KeyGeneratorSpi {
*/
protected SecretKey engineGenerateKey() {
if (this.random == null) {
- this.random = SunJCE.RANDOM;
+ this.random = SunJCE.getRandom();
}
byte[] keyBytes = new byte[this.keysize];
diff --git a/src/share/classes/com/sun/crypto/provider/CipherCore.java b/src/share/classes/com/sun/crypto/provider/CipherCore.java
index eb30879b0b97666f216bcf4c7ff96ccc68efc8bc..5c35c038915d9e05c0233ac2a13450b8d4cace21 100644
--- a/src/share/classes/com/sun/crypto/provider/CipherCore.java
+++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
package com.sun.crypto.provider;
+import java.util.Arrays;
import java.util.Locale;
import java.security.*;
@@ -59,7 +60,7 @@ final class CipherCore {
private byte[] buffer = null;
/*
- * internal buffer
+ * block size of cipher in bytes
*/
private int blockSize = 0;
@@ -76,10 +77,12 @@ final class CipherCore {
/*
* minimum number of bytes in the buffer required for
* FeedbackCipher.encryptFinal()/decryptFinal() call.
- * update() must buffer this many bytes before before starting
+ * update() must buffer this many bytes before starting
* to encrypt/decrypt data.
- * currently, only CTS mode has a non-zero value due to its special
- * handling on the last two blocks (the last one may be incomplete).
+ * currently, only the following cases have non-zero values:
+ * 1) CTS mode - due to its special handling on the last two blocks
+ * (the last one may be incomplete).
+ * 2) GCM mode + decryption - due to its trailing tag bytes
*/
private int minBytes = 0;
@@ -121,6 +124,24 @@ final class CipherCore {
private static final int PCBC_MODE = 4;
private static final int CTR_MODE = 5;
private static final int CTS_MODE = 6;
+ private static final int GCM_MODE = 7;
+
+ /*
+ * variables used for performing the GCM (key+iv) uniqueness check.
+ * To use GCM mode safely, the cipher object must be re-initialized
+ * with a different combination of key + iv values for each
+ * encryption operation. However, checking all past key + iv values
+ * isn't feasible. Thus, we only do a per-instance check of the
+ * key + iv values used in previous encryption.
+ * For decryption operations, no checking is necessary.
+ * NOTE: this key+iv check have to be done inside CipherCore class
+ * since CipherCore class buffers potential tag bytes in GCM mode
+ * and may not call GaloisCounterMode when there isn't sufficient
+ * input to process.
+ */
+ private boolean requireReinit = false;
+ private byte[] lastEncKey = null;
+ private byte[] lastEncIv = null;
/**
* Creates an instance of CipherCore with default ECB mode and
@@ -149,7 +170,7 @@ final class CipherCore {
* @param mode the cipher mode
*
* @exception NoSuchAlgorithmException if the requested cipher mode does
- * not exist
+ * not exist for this cipher
*/
void setMode(String mode) throws NoSuchAlgorithmException {
if (mode == null)
@@ -165,30 +186,34 @@ final class CipherCore {
if (modeUpperCase.equals("CBC")) {
cipherMode = CBC_MODE;
cipher = new CipherBlockChaining(rawImpl);
- }
- else if (modeUpperCase.equals("CTS")) {
+ } else if (modeUpperCase.equals("CTS")) {
cipherMode = CTS_MODE;
cipher = new CipherTextStealing(rawImpl);
minBytes = blockSize+1;
padding = null;
- }
- else if (modeUpperCase.equals("CTR")) {
+ } else if (modeUpperCase.equals("CTR")) {
cipherMode = CTR_MODE;
cipher = new CounterMode(rawImpl);
unitBytes = 1;
padding = null;
- }
- else if (modeUpperCase.startsWith("CFB")) {
+ } else if (modeUpperCase.startsWith("GCM")) {
+ // can only be used for block ciphers w/ 128-bit block size
+ if (blockSize != 16) {
+ throw new NoSuchAlgorithmException
+ ("GCM mode can only be used for AES cipher");
+ }
+ cipherMode = GCM_MODE;
+ cipher = new GaloisCounterMode(rawImpl);
+ padding = null;
+ } else if (modeUpperCase.startsWith("CFB")) {
cipherMode = CFB_MODE;
unitBytes = getNumOfUnit(mode, "CFB".length(), blockSize);
cipher = new CipherFeedback(rawImpl, unitBytes);
- }
- else if (modeUpperCase.startsWith("OFB")) {
+ } else if (modeUpperCase.startsWith("OFB")) {
cipherMode = OFB_MODE;
unitBytes = getNumOfUnit(mode, "OFB".length(), blockSize);
cipher = new OutputFeedback(rawImpl, unitBytes);
- }
- else if (modeUpperCase.equals("PCBC")) {
+ } else if (modeUpperCase.equals("PCBC")) {
cipherMode = PCBC_MODE;
cipher = new PCBC(rawImpl);
}
@@ -219,6 +244,7 @@ final class CipherCore {
return result;
}
+
/**
* Sets the padding mechanism of this cipher.
*
@@ -242,11 +268,27 @@ final class CipherCore {
+ " not implemented");
}
if ((padding != null) &&
- ((cipherMode == CTR_MODE) || (cipherMode == CTS_MODE))) {
+ ((cipherMode == CTR_MODE) || (cipherMode == CTS_MODE)
+ || (cipherMode == GCM_MODE))) {
padding = null;
- throw new NoSuchPaddingException
- ((cipherMode == CTR_MODE? "CTR":"CTS") +
- " mode must be used with NoPadding");
+ String modeStr = null;
+ switch (cipherMode) {
+ case CTR_MODE:
+ modeStr = "CTR";
+ break;
+ case GCM_MODE:
+ modeStr = "GCM";
+ break;
+ case CTS_MODE:
+ modeStr = "CTS";
+ break;
+ default:
+ // should never happen
+ }
+ if (modeStr != null) {
+ throw new NoSuchPaddingException
+ (modeStr + " mode must be used with NoPadding");
+ }
}
}
@@ -257,7 +299,7 @@ final class CipherCore {
* inputLen
(in bytes).
*
*
This call takes into account any unprocessed (buffered) data from a
- * previous update
call, and padding.
+ * previous update
call, padding, and AEAD tagging.
*
*
The actual output length of the next update
or
* doFinal
call may be smaller than the length returned by
@@ -270,23 +312,60 @@ final class CipherCore {
int getOutputSize(int inputLen) {
int totalLen = buffered + inputLen;
- if (padding == null)
+ // GCM: this call may be for either update() or doFinal(), so have to
+ // return the larger value of both
+ // Encryption: based on doFinal value: inputLen + tag
+ // Decryption: based on update value: inputLen
+ if (!decrypting && (cipherMode == GCM_MODE)) {
+ return (totalLen + ((GaloisCounterMode) cipher).getTagLen());
+ }
+
+ if (padding == null) {
return totalLen;
+ }
- if (decrypting)
+ if (decrypting) {
return totalLen;
+ }
if (unitBytes != blockSize) {
- if (totalLen < diffBlocksize)
+ if (totalLen < diffBlocksize) {
return diffBlocksize;
- else
+ } else {
return (totalLen + blockSize -
((totalLen - diffBlocksize) % blockSize));
+ }
} else {
return totalLen + padding.padLength(totalLen);
}
}
+ private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) {
+ int totalLen = 0;
+ switch (cipherMode) {
+ case GCM_MODE:
+ totalLen = buffered + inputLen;
+ if (isDoFinal) {
+ int tagLen = ((GaloisCounterMode) cipher).getTagLen();
+ if (decrypting) {
+ // need to get the actual value from cipher??
+ // deduct tagLen
+ totalLen -= tagLen;
+ } else {
+ totalLen += tagLen;
+ }
+ }
+ if (totalLen < 0) {
+ totalLen = 0;
+ }
+ break;
+ default:
+ totalLen = getOutputSize(inputLen);
+ break;
+ }
+ return totalLen;
+ }
+
/**
* Returns the initialization vector (IV) in a new buffer.
*
@@ -318,34 +397,49 @@ final class CipherCore {
* does not use any parameters.
*/
AlgorithmParameters getParameters(String algName) {
+ if (cipherMode == ECB_MODE) {
+ return null;
+ }
AlgorithmParameters params = null;
- if (cipherMode == ECB_MODE) return null;
+ AlgorithmParameterSpec spec;
byte[] iv = getIV();
- if (iv != null) {
- AlgorithmParameterSpec ivSpec;
- if (algName.equals("RC2")) {
- RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher();
- ivSpec = new RC2ParameterSpec(rawImpl.getEffectiveKeyBits(),
- iv);
+ if (iv == null) {
+ // generate spec using default value
+ if (cipherMode == GCM_MODE) {
+ iv = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
} else {
- ivSpec = new IvParameterSpec(iv);
- }
- try {
- params = AlgorithmParameters.getInstance(algName, "SunJCE");
- } catch (NoSuchAlgorithmException nsae) {
- // should never happen
- throw new RuntimeException("Cannot find " + algName +
- " AlgorithmParameters implementation in SunJCE provider");
- } catch (NoSuchProviderException nspe) {
- // should never happen
- throw new RuntimeException("Cannot find SunJCE provider");
- }
- try {
- params.init(ivSpec);
- } catch (InvalidParameterSpecException ipse) {
- // should never happen
- throw new RuntimeException("IvParameterSpec not supported");
+ iv = new byte[blockSize];
}
+ SunJCE.getRandom().nextBytes(iv);
+ }
+ if (cipherMode == GCM_MODE) {
+ algName = "GCM";
+ spec = new GCMParameterSpec
+ (((GaloisCounterMode) cipher).getTagLen()*8, iv);
+ } else {
+ if (algName.equals("RC2")) {
+ RC2Crypt rawImpl = (RC2Crypt) cipher.getEmbeddedCipher();
+ spec = new RC2ParameterSpec
+ (rawImpl.getEffectiveKeyBits(), iv);
+ } else {
+ spec = new IvParameterSpec(iv);
+ }
+ }
+ try {
+ params = AlgorithmParameters.getInstance(algName, "SunJCE");
+ } catch (NoSuchAlgorithmException nsae) {
+ // should never happen
+ throw new RuntimeException("Cannot find " + algName +
+ " AlgorithmParameters implementation in SunJCE provider");
+ } catch (NoSuchProviderException nspe) {
+ // should never happen
+ throw new RuntimeException("Cannot find SunJCE provider");
+ }
+ try {
+ params.init(spec);
+ } catch (InvalidParameterSpecException ipse) {
+ // should never happen
+ throw new RuntimeException(spec.getClass() + " not supported");
}
return params;
}
@@ -420,44 +514,63 @@ final class CipherCore {
|| (opmode == Cipher.UNWRAP_MODE);
byte[] keyBytes = getKeyBytes(key);
-
- byte[] ivBytes;
- if (params == null) {
- ivBytes = null;
- } else if (params instanceof IvParameterSpec) {
- ivBytes = ((IvParameterSpec)params).getIV();
- if ((ivBytes == null) || (ivBytes.length != blockSize)) {
- throw new InvalidAlgorithmParameterException
- ("Wrong IV length: must be " + blockSize +
- " bytes long");
- }
- } else if (params instanceof RC2ParameterSpec) {
- ivBytes = ((RC2ParameterSpec)params).getIV();
- if ((ivBytes != null) && (ivBytes.length != blockSize)) {
- throw new InvalidAlgorithmParameterException
- ("Wrong IV length: must be " + blockSize +
- " bytes long");
+ int tagLen = -1;
+ byte[] ivBytes = null;
+ if (params != null) {
+ if (cipherMode == GCM_MODE) {
+ if (params instanceof GCMParameterSpec) {
+ tagLen = ((GCMParameterSpec)params).getTLen();
+ if (tagLen < 96 || tagLen > 128 || ((tagLen & 0x07) != 0)) {
+ throw new InvalidAlgorithmParameterException
+ ("Unsupported TLen value; must be one of " +
+ "{128, 120, 112, 104, 96}");
+ }
+ tagLen = tagLen >> 3;
+ ivBytes = ((GCMParameterSpec)params).getIV();
+ } else {
+ throw new InvalidAlgorithmParameterException
+ ("Unsupported parameter: " + params);
+ }
+ } else {
+ if (params instanceof IvParameterSpec) {
+ ivBytes = ((IvParameterSpec)params).getIV();
+ if ((ivBytes == null) || (ivBytes.length != blockSize)) {
+ throw new InvalidAlgorithmParameterException
+ ("Wrong IV length: must be " + blockSize +
+ " bytes long");
+ }
+ } else if (params instanceof RC2ParameterSpec) {
+ ivBytes = ((RC2ParameterSpec)params).getIV();
+ if ((ivBytes != null) && (ivBytes.length != blockSize)) {
+ throw new InvalidAlgorithmParameterException
+ ("Wrong IV length: must be " + blockSize +
+ " bytes long");
+ }
+ } else {
+ throw new InvalidAlgorithmParameterException
+ ("Unsupported parameter: " + params);
+ }
}
- } else {
- throw new InvalidAlgorithmParameterException("Wrong parameter "
- + "type: IV "
- + "expected");
}
-
if (cipherMode == ECB_MODE) {
if (ivBytes != null) {
throw new InvalidAlgorithmParameterException
("ECB mode cannot use IV");
}
- } else if (ivBytes == null) {
+ } else if (ivBytes == null) {
if (decrypting) {
throw new InvalidAlgorithmParameterException("Parameters "
+ "missing");
}
+
if (random == null) {
- random = SunJCE.RANDOM;
+ random = SunJCE.getRandom();
+ }
+ if (cipherMode == GCM_MODE) {
+ ivBytes = new byte[GaloisCounterMode.DEFAULT_IV_LEN];
+ } else {
+ ivBytes = new byte[blockSize];
}
- ivBytes = new byte[blockSize];
random.nextBytes(ivBytes);
}
@@ -466,23 +579,57 @@ final class CipherCore {
String algorithm = key.getAlgorithm();
- cipher.init(decrypting, algorithm, keyBytes, ivBytes);
+ // GCM mode needs additional handling
+ if (cipherMode == GCM_MODE) {
+ if(tagLen == -1) {
+ tagLen = GaloisCounterMode.DEFAULT_TAG_LEN;
+ }
+ if (decrypting) {
+ minBytes = tagLen;
+ } else {
+ // check key+iv for encryption in GCM mode
+ requireReinit =
+ Arrays.equals(ivBytes, lastEncIv) &&
+ Arrays.equals(keyBytes, lastEncKey);
+ if (requireReinit) {
+ throw new InvalidAlgorithmParameterException
+ ("Cannot reuse iv for GCM encryption");
+ }
+ lastEncIv = ivBytes;
+ lastEncKey = keyBytes;
+ }
+ ((GaloisCounterMode) cipher).init
+ (decrypting, algorithm, keyBytes, ivBytes, tagLen);
+ } else {
+ cipher.init(decrypting, algorithm, keyBytes, ivBytes);
+ }
+ // skip checking key+iv from now on until after doFinal()
+ requireReinit = false;
}
void init(int opmode, Key key, AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- IvParameterSpec ivSpec = null;
+ AlgorithmParameterSpec spec = null;
+ String paramType = null;
if (params != null) {
try {
- ivSpec = params.getParameterSpec(IvParameterSpec.class);
+ if (cipherMode == GCM_MODE) {
+ paramType = "GCM";
+ spec = params.getParameterSpec(GCMParameterSpec.class);
+ } else {
+ // NOTE: RC2 parameters are always handled through
+ // init(..., AlgorithmParameterSpec,...) method, so
+ // we can assume IvParameterSpec type here.
+ paramType = "IV";
+ spec = params.getParameterSpec(IvParameterSpec.class);
+ }
} catch (InvalidParameterSpecException ipse) {
- throw new InvalidAlgorithmParameterException("Wrong parameter "
- + "type: IV "
- + "expected");
+ throw new InvalidAlgorithmParameterException
+ ("Wrong parameter type: " + paramType + " expected");
}
}
- init(opmode, key, ivSpec, random);
+ init(opmode, key, spec, random);
}
/**
@@ -504,6 +651,7 @@ final class CipherCore {
return keyBytes;
}
+
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
@@ -524,22 +672,25 @@ final class CipherCore {
* (e.g., has not been initialized)
*/
byte[] update(byte[] input, int inputOffset, int inputLen) {
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
+
byte[] output = null;
- byte[] out = null;
try {
- output = new byte[getOutputSize(inputLen)];
+ output = new byte[getOutputSizeByOperation(inputLen, false)];
int len = update(input, inputOffset, inputLen, output,
0);
if (len == output.length) {
- out = output;
+ return output;
} else {
- out = new byte[len];
- System.arraycopy(output, 0, out, 0, len);
+ return Arrays.copyOf(output, len);
}
} catch (ShortBufferException e) {
- // never thrown
+ // should never happen
+ throw new ProviderException("Unexpected exception", e);
}
- return out;
}
/**
@@ -567,6 +718,11 @@ final class CipherCore {
*/
int update(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException {
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
+
// figure out how much can be sent to crypto function
int len = buffered + inputLen - minBytes;
if (padding != null && decrypting) {
@@ -582,6 +738,7 @@ final class CipherCore {
+ "(at least) " + len
+ " bytes long");
}
+
if (len != 0) {
// there is some work to do
byte[] in = new byte[len];
@@ -600,7 +757,6 @@ final class CipherCore {
System.arraycopy(input, inputOffset, in,
bufferedConsumed, inputConsumed);
}
-
if (decrypting) {
cipher.decrypt(in, 0, len, output, outputOffset);
} else {
@@ -611,11 +767,12 @@ final class CipherCore {
// the total input length a multiple of blocksize when
// padding is applied
if (unitBytes != blockSize) {
- if (len < diffBlocksize)
+ if (len < diffBlocksize) {
diffBlocksize -= len;
- else
+ } else {
diffBlocksize = blockSize -
((len - diffBlocksize) % blockSize);
+ }
}
inputLen -= inputConsumed;
@@ -669,21 +826,18 @@ final class CipherCore {
byte[] doFinal(byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException, BadPaddingException {
byte[] output = null;
- byte[] out = null;
try {
- output = new byte[getOutputSize(inputLen)];
+ output = new byte[getOutputSizeByOperation(inputLen, true)];
int len = doFinal(input, inputOffset, inputLen, output, 0);
if (len < output.length) {
- out = new byte[len];
- if (len != 0)
- System.arraycopy(output, 0, out, 0, len);
+ return Arrays.copyOf(output, len);
} else {
- out = output;
+ return output;
}
} catch (ShortBufferException e) {
// never thrown
+ throw new ProviderException("Unexpected exception", e);
}
- return out;
}
/**
@@ -726,6 +880,10 @@ final class CipherCore {
int outputOffset)
throws IllegalBlockSizeException, ShortBufferException,
BadPaddingException {
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
// calculate the total input length
int totalLen = buffered + inputLen;
@@ -752,8 +910,9 @@ final class CipherCore {
}
// if encrypting and padding not null, add padding
- if (!decrypting && padding != null)
+ if (!decrypting && padding != null) {
paddedLen += paddingLen;
+ }
// check output buffer capacity.
// if we are decrypting with padding applied, we can perform this
@@ -763,8 +922,8 @@ final class CipherCore {
throw new ShortBufferException("Output buffer is null");
}
int outputCapacity = output.length - outputOffset;
- if (((!decrypting) || (padding == null)) &&
- (outputCapacity < paddedLen) ||
+
+ if (((!decrypting) && (outputCapacity < paddedLen)) ||
(decrypting && (outputCapacity < (paddedLen - blockSize)))) {
throw new ShortBufferException("Output buffer too short: "
+ outputCapacity + " bytes given, "
@@ -812,6 +971,7 @@ final class CipherCore {
}
totalLen = padStart;
}
+
if ((output.length - outputOffset) < totalLen) {
// restore so users can retry with a larger buffer
cipher.restore();
@@ -824,8 +984,13 @@ final class CipherCore {
output[outputOffset + i] = outWithPadding[i];
}
} else { // encrypting
- totalLen = finalNoPadding(finalBuf, finalOffset, output,
- outputOffset, paddedLen);
+ try {
+ totalLen = finalNoPadding(finalBuf, finalOffset, output,
+ outputOffset, paddedLen);
+ } finally {
+ // reset after doFinal() for GCM encryption
+ requireReinit = (cipherMode == GCM_MODE);
+ }
}
buffered = 0;
@@ -836,33 +1001,33 @@ final class CipherCore {
return totalLen;
}
- private int finalNoPadding(byte[] in, int inOff, byte[] out, int outOff,
+ private int finalNoPadding(byte[] in, int inOfs, byte[] out, int outOfs,
int len)
- throws IllegalBlockSizeException
- {
- if (in == null || len == 0)
- return 0;
+ throws IllegalBlockSizeException, AEADBadTagException {
- if ((cipherMode != CFB_MODE) && (cipherMode != OFB_MODE)
- && ((len % unitBytes) != 0) && (cipherMode != CTS_MODE)) {
- if (padding != null) {
- throw new IllegalBlockSizeException
- ("Input length (with padding) not multiple of " +
- unitBytes + " bytes");
- } else {
- throw new IllegalBlockSizeException
- ("Input length not multiple of " + unitBytes
- + " bytes");
- }
+ if ((cipherMode != GCM_MODE) && (in == null || len == 0)) {
+ return 0;
}
-
+ if ((cipherMode != CFB_MODE) && (cipherMode != OFB_MODE) &&
+ (cipherMode != GCM_MODE) &&
+ ((len % unitBytes) != 0) && (cipherMode != CTS_MODE)) {
+ if (padding != null) {
+ throw new IllegalBlockSizeException
+ ("Input length (with padding) not multiple of " +
+ unitBytes + " bytes");
+ } else {
+ throw new IllegalBlockSizeException
+ ("Input length not multiple of " + unitBytes
+ + " bytes");
+ }
+ }
+ int outLen = 0;
if (decrypting) {
- cipher.decryptFinal(in, inOff, len, out, outOff);
+ outLen = cipher.decryptFinal(in, inOfs, len, out, outOfs);
} else {
- cipher.encryptFinal(in, inOff, len, out, outOff);
+ outLen = cipher.encryptFinal(in, inOfs, len, out, outOfs);
}
-
- return len;
+ return outLen;
}
// Note: Wrap() and Unwrap() are the same in
@@ -939,4 +1104,36 @@ final class CipherCore {
return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
wrappedKeyType);
}
+
+ /**
+ * Continues a multi-part update of the Additional Authentication
+ * Data (AAD), using a subset of the provided buffer.
+ *
+ * Calls to this method provide AAD to the cipher when operating in
+ * modes such as AEAD (GCM/CCM). If this cipher is operating in
+ * either GCM or CCM mode, all AAD must be supplied before beginning
+ * operations on the ciphertext (via the {@code update} and {@code
+ * doFinal} methods).
+ *
+ * @param src the buffer containing the AAD
+ * @param offset the offset in {@code src} where the AAD input starts
+ * @param len the number of AAD bytes
+ *
+ * @throws IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized), does not accept AAD, or if
+ * operating in either GCM or CCM mode and one of the {@code update}
+ * methods has already been called for the active
+ * encryption/decryption operation
+ * @throws UnsupportedOperationException if this method
+ * has not been overridden by an implementation
+ *
+ * @since 1.8
+ */
+ void updateAAD(byte[] src, int offset, int len) {
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
+ cipher.updateAAD(src, offset, len);
+ }
}
diff --git a/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java b/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java
index ef77d3e5360bfe05c3d8d3c6e80ce6d729d6f3f1..630f8707fdeb7f2c582dfaba6dab0bf7fade9d55 100644
--- a/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java
+++ b/src/share/classes/com/sun/crypto/provider/CipherTextStealing.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -83,9 +83,10 @@ final class CipherTextStealing extends CipherBlockChaining {
* @param plainLen the length of the input data
* @param cipher the buffer for the result
* @param cipherOffset the offset in cipher
+ * @return the number of bytes placed into cipher
*/
- void encryptFinal(byte[] plain, int plainOffset, int plainLen,
- byte[] cipher, int cipherOffset)
+ int encryptFinal(byte[] plain, int plainOffset, int plainLen,
+ byte[] cipher, int cipherOffset)
throws IllegalBlockSizeException {
if (plainLen < blockSize) {
@@ -134,6 +135,7 @@ final class CipherTextStealing extends CipherBlockChaining {
embeddedCipher.encryptBlock(tmp2, 0, cipher, cipherOffset);
}
}
+ return plainLen;
}
/**
@@ -158,9 +160,10 @@ final class CipherTextStealing extends CipherBlockChaining {
* @param cipherLen the length of the input data
* @param plain the buffer for the result
* @param plainOffset the offset in plain
+ * @return the number of bytes placed into plain
*/
- void decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
- byte[] plain, int plainOffset)
+ int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
+ byte[] plain, int plainOffset)
throws IllegalBlockSizeException {
if (cipherLen < blockSize) {
throw new IllegalBlockSizeException("input is too short!");
@@ -211,5 +214,6 @@ final class CipherTextStealing extends CipherBlockChaining {
}
}
}
+ return cipherLen;
}
}
diff --git a/src/share/classes/com/sun/crypto/provider/DESKeyGenerator.java b/src/share/classes/com/sun/crypto/provider/DESKeyGenerator.java
index b082a9934088467f39e7a17a85555390d5c4fe37..cca8659974fc9a1c5b8106552d9922611791e0c6 100644
--- a/src/share/classes/com/sun/crypto/provider/DESKeyGenerator.java
+++ b/src/share/classes/com/sun/crypto/provider/DESKeyGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -102,7 +102,7 @@ public final class DESKeyGenerator extends KeyGeneratorSpi {
DESKey desKey = null;
if (this.random == null) {
- this.random = SunJCE.RANDOM;
+ this.random = SunJCE.getRandom();
}
try {
diff --git a/src/share/classes/com/sun/crypto/provider/DESedeKeyGenerator.java b/src/share/classes/com/sun/crypto/provider/DESedeKeyGenerator.java
index 42c09c0c2b785d791969cd2c28cc5ef775400d50..28684b0f9e7af67973122bb7d20ea9032dd8a66d 100644
--- a/src/share/classes/com/sun/crypto/provider/DESedeKeyGenerator.java
+++ b/src/share/classes/com/sun/crypto/provider/DESedeKeyGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -105,7 +105,7 @@ public final class DESedeKeyGenerator extends KeyGeneratorSpi {
*/
protected SecretKey engineGenerateKey() {
if (this.random == null) {
- this.random = SunJCE.RANDOM;
+ this.random = SunJCE.getRandom();
}
byte[] rawkey = new byte[DESedeKeySpec.DES_EDE_KEY_LEN];
diff --git a/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java b/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java
index 07b5a778dcaa491a5575ffde0dd78df610450559..4a87b5b1faed35dedb015499e7b51490f89c30ac 100644
--- a/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java
+++ b/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -217,7 +217,7 @@ public final class DESedeWrapCipher extends CipherSpi {
if (params == null) {
iv = new byte[8];
if (random == null) {
- random = SunJCE.RANDOM;
+ random = SunJCE.getRandom();
}
random.nextBytes(iv);
}
diff --git a/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java b/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java
index 533d80d49af2d5f08517e90cb37b6758e43aa223..6ae39e25e7e0b17eef23b7cc751fd22f574ec8e4 100644
--- a/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java
+++ b/src/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,7 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi {
*/
public KeyPair generateKeyPair() {
if (random == null) {
- random = SunJCE.RANDOM;
+ random = SunJCE.getRandom();
}
if (params == null) {
diff --git a/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java b/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java
index 0088729d27d47b7249bb160d3a530d1776312d2d..a976da099fba0f38d87e202b0edb44cf8692c27b 100644
--- a/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java
+++ b/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -131,7 +131,7 @@ extends AlgorithmParameterGeneratorSpi {
}
if (this.random == null)
- this.random = SunJCE.RANDOM;
+ this.random = SunJCE.getRandom();
try {
AlgorithmParameterGenerator paramGen;
diff --git a/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java b/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java
index 34b83ae928b342720f521e08901c5d01561b33b7..c27332457f3bf9ced8fd680b9c11eab890f3afe3 100644
--- a/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java
+++ b/src/share/classes/com/sun/crypto/provider/FeedbackCipher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
package com.sun.crypto.provider;
import java.security.InvalidKeyException;
-import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.*;
/**
* This class represents a block cipher in one of its modes. It wraps
@@ -150,11 +150,13 @@ abstract class FeedbackCipher {
* @param plainLen the length of the input data
* @param cipher the buffer for the encryption result
* @param cipherOffset the offset in cipher
+ * @return the number of bytes placed into cipher
*/
- void encryptFinal(byte[] plain, int plainOffset, int plainLen,
- byte[] cipher, int cipherOffset)
+ int encryptFinal(byte[] plain, int plainOffset, int plainLen,
+ byte[] cipher, int cipherOffset)
throws IllegalBlockSizeException {
encrypt(plain, plainOffset, plainLen, cipher, cipherOffset);
+ return plainLen;
}
/**
* Performs decryption operation.
@@ -190,10 +192,40 @@ abstract class FeedbackCipher {
* @param cipherLen the length of the input data
* @param plain the buffer for the decryption result
* @param plainOffset the offset in plain
+ * @return the number of bytes placed into plain
*/
- void decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
- byte[] plain, int plainOffset)
- throws IllegalBlockSizeException {
+ int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
+ byte[] plain, int plainOffset)
+ throws IllegalBlockSizeException, AEADBadTagException {
decrypt(cipher, cipherOffset, cipherLen, plain, plainOffset);
+ return cipherLen;
}
+
+ /**
+ * Continues a multi-part update of the Additional Authentication
+ * Data (AAD), using a subset of the provided buffer. If this
+ * cipher is operating in either GCM or CCM mode, all AAD must be
+ * supplied before beginning operations on the ciphertext (via the
+ * {@code update} and {@code doFinal} methods).
+ *
+ * NOTE: Given most modes do not accept AAD, default impl for this + * method throws IllegalStateException. + * + * @param src the buffer containing the AAD + * @param offset the offset in {@code src} where the AAD input starts + * @param len the number of AAD bytes + * + * @throws IllegalStateException if this cipher is in a wrong state + * (e.g., has not been initialized), does not accept AAD, or if + * operating in either GCM or CCM mode and one of the {@code update} + * methods has already been called for the active + * encryption/decryption operation + * @throws UnsupportedOperationException if this method + * has not been overridden by an implementation + * + * @since 1.8 + */ + void updateAAD(byte[] src, int offset, int len) { + throw new IllegalStateException("No AAD accepted"); + } } diff --git a/src/share/classes/com/sun/crypto/provider/GCMParameters.java b/src/share/classes/com/sun/crypto/provider/GCMParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..4ae729204a6590c16df16177c67476cca8586ef0 --- /dev/null +++ b/src/share/classes/com/sun/crypto/provider/GCMParameters.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.crypto.provider; + +import java.io.IOException; +import java.security.AlgorithmParametersSpi; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; +import javax.crypto.spec.GCMParameterSpec; +import sun.misc.HexDumpEncoder; +import sun.security.util.*; + +/** + * This class implements the parameter set used with + * GCM encryption, which is defined in RFC 5084 as follows: + * + *
+ * GCMParameters ::= SEQUENCE { + * aes-iv OCTET STRING, -- recommended size is 12 octets + * aes-tLen AES-GCM-ICVlen DEFAULT 12 } + * + * AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16) + * + *+ * + * @author Valerie Peng + * @since 1.8 + */ +public final class GCMParameters extends AlgorithmParametersSpi { + + // the iv + private byte[] iv; + // the tag length in bytes + private int tLen; + + public GCMParameters() {} + + protected void engineInit(AlgorithmParameterSpec paramSpec) + throws InvalidParameterSpecException { + + if (!(paramSpec instanceof GCMParameterSpec)) { + throw new InvalidParameterSpecException + ("Inappropriate parameter specification"); + } + GCMParameterSpec gps = (GCMParameterSpec) paramSpec; + // need to convert from bits to bytes for ASN.1 encoding + this.tLen = gps.getTLen()/8; + this.iv = gps.getIV(); + } + + protected void engineInit(byte[] encoded) throws IOException { + DerValue val = new DerValue(encoded); + // check if IV or params + if (val.tag == DerValue.tag_Sequence) { + byte[] iv = val.data.getOctetString(); + int tLen; + if (val.data.available() != 0) { + tLen = val.data.getInteger(); + if (tLen < 12 || tLen > 16 ) { + throw new IOException + ("GCM parameter parsing error: unsupported tag len: " + + tLen); + } + if (val.data.available() != 0) { + throw new IOException + ("GCM parameter parsing error: extra data"); + } + } else { + tLen = 12; + } + this.iv = iv.clone(); + this.tLen = tLen; + } else { + throw new IOException("GCM parameter parsing error: no SEQ tag"); + } + } + + protected void engineInit(byte[] encoded, String decodingMethod) + throws IOException { + engineInit(encoded); + } + + protected
This function is used in the implementation of GCM mode. + * + * @since 1.8 + */ +final class GCTR { + + // these fields should not change after the object has been constructed + private final SymmetricCipher aes; + private final byte[] icb; + + // the current counter value + private byte[] counter; + + // needed for save/restore calls + private byte[] counterSave; + + // NOTE: cipher should already be initialized + GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) { + this.aes = cipher; + this.icb = initialCounterBlk; + this.counter = icb.clone(); + } + + // input must be multiples of 128-bit blocks when calling update + int update(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) { + if (inLen - inOfs > in.length) { + throw new RuntimeException("input length out of bound"); + } + if (inLen < 0 || inLen % AES_BLOCK_SIZE != 0) { + throw new RuntimeException("input length unsupported"); + } + if (out.length - outOfs < inLen) { + throw new RuntimeException("output buffer too small"); + } + + byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; + + int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE; + for (int i = 0; i < numOfCompleteBlocks; i++) { + aes.encryptBlock(counter, 0, encryptedCntr, 0); + for (int n = 0; n < AES_BLOCK_SIZE; n++) { + int index = (i * AES_BLOCK_SIZE + n); + out[outOfs + index] = + (byte) ((in[inOfs + index] ^ encryptedCntr[n])); + } + GaloisCounterMode.increment32(counter); + } + return inLen; + } + + // input can be arbitrary size when calling doFinal + protected int doFinal(byte[] in, int inOfs, int inLen, byte[] out, + int outOfs) throws IllegalBlockSizeException { + try { + if (inLen < 0) { + throw new IllegalBlockSizeException("Negative input size!"); + } else if (inLen > 0) { + int lastBlockSize = inLen % AES_BLOCK_SIZE; + // process the complete blocks first + update(in, inOfs, inLen - lastBlockSize, out, outOfs); + if (lastBlockSize != 0) { + // do the last partial block + byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; + aes.encryptBlock(counter, 0, encryptedCntr, 0); + + int processed = inLen - lastBlockSize; + for (int n = 0; n < lastBlockSize; n++) { + out[outOfs + processed + n] = + (byte) ((in[inOfs + processed + n] ^ + encryptedCntr[n])); + } + } + } + } finally { + reset(); + } + return inLen; + } + + /** + * Resets the current counter to its initial value. + * This is used after the doFinal() is called so this object can be + * reused w/o explicit re-initialization. + */ + void reset() { + System.arraycopy(icb, 0, counter, 0, icb.length); + } + + /** + * Save the current content of this object. + */ + void save() { + this.counterSave = this.counter.clone(); + } + + /** + * Restores the content of this object to the previous saved one. + */ + void restore() { + this.counter = this.counterSave; + } +} diff --git a/src/share/classes/com/sun/crypto/provider/GHASH.java b/src/share/classes/com/sun/crypto/provider/GHASH.java new file mode 100644 index 0000000000000000000000000000000000000000..8b0ba28e8980776eb79c60e0c2e00474aa7bce2b --- /dev/null +++ b/src/share/classes/com/sun/crypto/provider/GHASH.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * (C) Copyright IBM Corp. 2013 + */ + +package com.sun.crypto.provider; + +import java.util.Arrays; +import java.security.*; +import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; + +/** + * This class represents the GHASH function defined in NIST 800-38D + * under section 6.4. It needs to be constructed w/ a hash subkey, i.e. + * block H. Given input of 128-bit blocks, it will process and output + * a 128-bit block. + * + *
This function is used in the implementation of GCM mode. + * + * @since 1.8 + */ +final class GHASH { + + private static final byte P128 = (byte) 0xe1; //reduction polynomial + + private static boolean getBit(byte[] b, int pos) { + int p = pos / 8; + pos %= 8; + int i = (b[p] >>> (7 - pos)) & 1; + return i != 0; + } + + private static void shift(byte[] b) { + byte temp, temp2; + temp2 = 0; + for (int i = 0; i < b.length; i++) { + temp = (byte) ((b[i] & 0x01) << 7); + b[i] = (byte) ((b[i] & 0xff) >>> 1); + b[i] = (byte) (b[i] | temp2); + temp2 = temp; + } + } + + // Given block X and Y, returns the muliplication of X * Y + private static byte[] blockMult(byte[] x, byte[] y) { + if (x.length != AES_BLOCK_SIZE || y.length != AES_BLOCK_SIZE) { + throw new RuntimeException("illegal input sizes"); + } + byte[] z = new byte[AES_BLOCK_SIZE]; + byte[] v = y.clone(); + // calculate Z1-Z127 and V1-V127 + for (int i = 0; i < 127; i++) { + // Zi+1 = Zi if bit i of x is 0 + if (getBit(x, i)) { + for (int n = 0; n < z.length; n++) { + z[n] ^= v[n]; + } + } + boolean lastBitOfV = getBit(v, 127); + shift(v); + if (lastBitOfV) v[0] ^= P128; + } + // calculate Z128 + if (getBit(x, 127)) { + for (int n = 0; n < z.length; n++) { + z[n] ^= v[n]; + } + } + return z; + } + + // hash subkey H; should not change after the object has been constructed + private final byte[] subkeyH; + + // buffer for storing hash + private byte[] state; + + // variables for save/restore calls + private byte[] stateSave = null; + + /** + * Initializes the cipher in the specified mode with the given key + * and iv. + * + * @param subkeyH the hash subkey + * + * @exception ProviderException if the given key is inappropriate for + * initializing this digest + */ + GHASH(byte[] subkeyH) throws ProviderException { + if ((subkeyH == null) || subkeyH.length != AES_BLOCK_SIZE) { + throw new ProviderException("Internal error"); + } + this.subkeyH = subkeyH; + this.state = new byte[AES_BLOCK_SIZE]; + } + + /** + * Resets the GHASH object to its original state, i.e. blank w/ + * the same subkey H. Used after digest() is called and to re-use + * this object for different data w/ the same H. + */ + void reset() { + Arrays.fill(state, (byte) 0); + } + + /** + * Save the current snapshot of this GHASH object. + */ + void save() { + stateSave = state.clone(); + } + + /** + * Restores this object using the saved snapshot. + */ + void restore() { + state = stateSave; + } + + private void processBlock(byte[] data, int ofs) { + if (data.length - ofs < AES_BLOCK_SIZE) { + throw new RuntimeException("need complete block"); + } + for (int n = 0; n < state.length; n++) { + state[n] ^= data[ofs + n]; + } + state = blockMult(state, subkeyH); + } + + void update(byte[] in) { + update(in, 0, in.length); + } + + void update(byte[] in, int inOfs, int inLen) { + if (inLen - inOfs > in.length) { + throw new RuntimeException("input length out of bound"); + } + if (inLen % AES_BLOCK_SIZE != 0) { + throw new RuntimeException("input length unsupported"); + } + + for (int i = inOfs; i < (inOfs + inLen); i += AES_BLOCK_SIZE) { + processBlock(in, i); + } + } + + byte[] digest() { + try { + return state.clone(); + } finally { + reset(); + } + } +} diff --git a/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java new file mode 100644 index 0000000000000000000000000000000000000000..a2c6cfd82ef3750fecfb96ce853c7e6006ebcdd4 --- /dev/null +++ b/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code.S + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.crypto.provider; + +import java.util.Arrays; +import java.io.*; +import java.security.*; +import javax.crypto.*; +import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; + +/** + * This class represents ciphers in GaloisCounter (GCM) mode. + * + *
This mode currently should only be used w/ AES cipher. + * Although no checking is done here, caller should only + * pass AES Cipher to the constructor. + * + *
NOTE: This class does not deal with buffering or padding. + * + * @since 1.8 + */ +final class GaloisCounterMode extends FeedbackCipher { + + static int DEFAULT_TAG_LEN = AES_BLOCK_SIZE; + static int DEFAULT_IV_LEN = 12; // in bytes + + // buffer for AAD data; if null, meaning update has been called + private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream(); + private int sizeOfAAD = 0; + + // in bytes; need to convert to bits (default value 128) when needed + private int tagLenBytes = DEFAULT_TAG_LEN; + + // these following 2 fields can only be initialized after init() is + // called, e.g. after cipher key k is set, and STAY UNCHANGED + private byte[] subkeyH = null; + private byte[] preCounterBlock = null; + + private GCTR gctrPAndC = null; + private GHASH ghashAllToS = null; + + // length of total data, i.e. len(C) + private int processed = 0; + + // additional variables for save/restore calls + private byte[] aadBufferSave = null; + private int sizeOfAADSave = 0; + private int processedSave = 0; + + // value must be 16-byte long; used by GCTR and GHASH as well + static void increment32(byte[] value) { + if (value.length != AES_BLOCK_SIZE) { + throw new RuntimeException("Unexpected counter block length"); + } + // start from last byte and only go over 4 bytes, i.e. total 32 bits + int n = value.length - 1; + while ((n >= value.length - 4) && (++value[n] == 0)) { + n--; + } + } + + // ivLen in bits + private static byte[] getLengthBlock(int ivLen) { + byte[] out = new byte[AES_BLOCK_SIZE]; + out[12] = (byte)(ivLen >>> 24); + out[13] = (byte)(ivLen >>> 16); + out[14] = (byte)(ivLen >>> 8); + out[15] = (byte)ivLen; + return out; + } + + // aLen and cLen both in bits + private static byte[] getLengthBlock(int aLen, int cLen) { + byte[] out = new byte[AES_BLOCK_SIZE]; + out[4] = (byte)(aLen >>> 24); + out[5] = (byte)(aLen >>> 16); + out[6] = (byte)(aLen >>> 8); + out[7] = (byte)aLen; + out[12] = (byte)(cLen >>> 24); + out[13] = (byte)(cLen >>> 16); + out[14] = (byte)(cLen >>> 8); + out[15] = (byte)cLen; + return out; + } + + private static byte[] expandToOneBlock(byte[] in, int inOfs, int len) { + if (len > AES_BLOCK_SIZE) { + throw new ProviderException("input " + len + " too long"); + } + if (len == AES_BLOCK_SIZE && inOfs == 0) { + return in; + } else { + byte[] paddedIn = new byte[AES_BLOCK_SIZE]; + System.arraycopy(in, inOfs, paddedIn, 0, len); + return paddedIn; + } + } + + private static byte[] getJ0(byte[] iv, byte[] subkeyH) { + byte[] j0; + if (iv.length == 12) { // 96 bits + j0 = expandToOneBlock(iv, 0, iv.length); + j0[AES_BLOCK_SIZE - 1] = 1; + } else { + GHASH g = new GHASH(subkeyH); + int lastLen = iv.length % AES_BLOCK_SIZE; + if (lastLen != 0) { + g.update(iv, 0, iv.length - lastLen); + byte[] padded = + expandToOneBlock(iv, iv.length - lastLen, lastLen); + g.update(padded); + } else { + g.update(iv); + } + byte[] lengthBlock = getLengthBlock(iv.length*8); + g.update(lengthBlock); + j0 = g.digest(); + } + return j0; + } + + GaloisCounterMode(SymmetricCipher embeddedCipher) { + super(embeddedCipher); + aadBuffer = new ByteArrayOutputStream(); + } + + /** + * Gets the name of the feedback mechanism + * + * @return the name of the feedback mechanism + */ + String getFeedback() { + return "GCM"; + } + + /** + * Resets the cipher object to its original state. + * This is used when doFinal is called in the Cipher class, so that the + * cipher can be reused (with its original key and iv). + */ + void reset() { + if (aadBuffer == null) { + aadBuffer = new ByteArrayOutputStream(); + } else { + aadBuffer.reset(); + } + if (gctrPAndC != null) gctrPAndC.reset(); + if (ghashAllToS != null) ghashAllToS.reset(); + processed = 0; + sizeOfAAD = 0; + } + + /** + * Save the current content of this cipher. + */ + void save() { + processedSave = processed; + sizeOfAADSave = sizeOfAAD; + aadBufferSave = + ((aadBuffer == null || aadBuffer.size() == 0)? + null : aadBuffer.toByteArray()); + if (gctrPAndC != null) gctrPAndC.save(); + if (ghashAllToS != null) ghashAllToS.save(); + } + + /** + * Restores the content of this cipher to the previous saved one. + */ + void restore() { + processed = processedSave; + sizeOfAAD = sizeOfAADSave; + if (aadBuffer != null) { + aadBuffer.reset(); + if (aadBufferSave != null) { + aadBuffer.write(aadBufferSave, 0, aadBufferSave.length); + } + } + if (gctrPAndC != null) gctrPAndC.restore(); + if (ghashAllToS != null) ghashAllToS.restore(); + } + + /** + * Initializes the cipher in the specified mode with the given key + * and iv. + * + * @param decrypting flag indicating encryption or decryption + * @param algorithm the algorithm name + * @param key the key + * @param iv the iv + * @param tagLenBytes the length of tag in bytes + * + * @exception InvalidKeyException if the given key is inappropriate for + * initializing this cipher + */ + void init(boolean decrypting, String algorithm, byte[] key, byte[] iv) + throws InvalidKeyException { + init(decrypting, algorithm, key, iv, DEFAULT_TAG_LEN); + } + + /** + * Initializes the cipher in the specified mode with the given key + * and iv. + * + * @param decrypting flag indicating encryption or decryption + * @param algorithm the algorithm name + * @param key the key + * @param iv the iv + * @param tagLenBytes the length of tag in bytes + * + * @exception InvalidKeyException if the given key is inappropriate for + * initializing this cipher + */ + void init(boolean decrypting, String algorithm, byte[] keyValue, + byte[] ivValue, int tagLenBytes) + throws InvalidKeyException { + if (keyValue == null || ivValue == null) { + throw new InvalidKeyException("Internal error"); + } + + // always encrypt mode for embedded cipher + this.embeddedCipher.init(false, algorithm, keyValue); + this.subkeyH = new byte[AES_BLOCK_SIZE]; + this.embeddedCipher.encryptBlock(new byte[AES_BLOCK_SIZE], 0, + this.subkeyH, 0); + + this.iv = ivValue.clone(); + preCounterBlock = getJ0(iv, subkeyH); + byte[] j0Plus1 = preCounterBlock.clone(); + increment32(j0Plus1); + gctrPAndC = new GCTR(embeddedCipher, j0Plus1); + ghashAllToS = new GHASH(subkeyH); + + this.tagLenBytes = tagLenBytes; + if (aadBuffer == null) { + aadBuffer = new ByteArrayOutputStream(); + } else { + aadBuffer.reset(); + } + processed = 0; + sizeOfAAD = 0; + } + + /** + * Continues a multi-part update of the Additional Authentication + * Data (AAD), using a subset of the provided buffer. If this + * cipher is operating in either GCM or CCM mode, all AAD must be + * supplied before beginning operations on the ciphertext (via the + * {@code update} and {@code doFinal} methods). + *
+ * NOTE: Given most modes do not accept AAD, default impl for this + * method throws IllegalStateException. + * + * @param src the buffer containing the AAD + * @param offset the offset in {@code src} where the AAD input starts + * @param len the number of AAD bytes + * + * @throws IllegalStateException if this cipher is in a wrong state + * (e.g., has not been initialized), does not accept AAD, or if + * operating in either GCM or CCM mode and one of the {@code update} + * methods has already been called for the active + * encryption/decryption operation + * @throws UnsupportedOperationException if this method + * has not been overridden by an implementation + * + * @since 1.8 + */ + void updateAAD(byte[] src, int offset, int len) { + if (aadBuffer != null) { + aadBuffer.write(src, offset, len); + } else { + // update has already been called + throw new IllegalStateException + ("Update has been called; no more AAD data"); + } + } + + // Feed the AAD data to GHASH, pad if necessary + void processAAD() { + if (aadBuffer != null) { + byte[] aad = aadBuffer.toByteArray(); + sizeOfAAD = aad.length; + aadBuffer = null; + + int lastLen = aad.length % AES_BLOCK_SIZE; + if (lastLen != 0) { + ghashAllToS.update(aad, 0, aad.length - lastLen); + byte[] padded = expandToOneBlock(aad, aad.length - lastLen, + lastLen); + ghashAllToS.update(padded); + } else { + ghashAllToS.update(aad); + } + } + } + + // Utility to process the last block; used by encryptFinal and decryptFinal + void doLastBlock(byte[] in, int inOfs, int len, byte[] out, int outOfs, + boolean isEncrypt) throws IllegalBlockSizeException { + // process data in 'in' + gctrPAndC.doFinal(in, inOfs, len, out, outOfs); + processed += len; + + byte[] ct; + int ctOfs; + if (isEncrypt) { + ct = out; + ctOfs = outOfs; + } else { + ct = in; + ctOfs = inOfs; + } + int lastLen = len % AES_BLOCK_SIZE; + if (lastLen != 0) { + ghashAllToS.update(ct, ctOfs, len - lastLen); + byte[] padded = + expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen); + ghashAllToS.update(padded); + } else { + ghashAllToS.update(ct, ctOfs, len); + } + } + + + /** + * Performs encryption operation. + * + *
The input plain text in
, starting at inOff
+ * and ending at (inOff + len - 1)
, is encrypted. The result
+ * is stored in out
, starting at outOfs
.
+ *
+ *
It is the application's responsibility to make sure that
+ * len
is a multiple of the embedded cipher's block size,
+ * otherwise, a ProviderException will be thrown.
+ *
+ *
It is also the application's responsibility to make sure that
+ * init
has been called before this method is called.
+ * (This check is omitted here, to avoid double checking.)
+ *
+ * @param in the buffer with the input data to be encrypted
+ * @param inOfs the offset in in
+ * @param len the length of the input data
+ * @param out the buffer for the result
+ * @param outOfs the offset in out
+ */
+ void encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
+ processAAD();
+ if (len > 0) {
+ gctrPAndC.update(in, inOfs, len, out, outOfs);
+ processed += len;
+ ghashAllToS.update(out, outOfs, len);
+ }
+ }
+
+ /**
+ * Performs encryption operation for the last time.
+ *
+ *
NOTE: len
may not be multiple of the embedded
+ * cipher's block size for this call.
+ *
+ * @param in the input buffer with the data to be encrypted
+ * @param inOfs the offset in in
+ * @param len the length of the input data
+ * @param out the buffer for the encryption result
+ * @param outOfs the offset in out
+ * @return the number of bytes placed into the out
buffer
+ */
+ int encryptFinal(byte[] in, int inOfs, int len, byte[] out, int outOfs)
+ throws IllegalBlockSizeException {
+ if (out.length - outOfs < (len + tagLenBytes)) {
+ throw new RuntimeException("Output buffer too small");
+ }
+
+ processAAD();
+ if (len > 0) {
+ //ByteUtil.dumpArray(Arrays.copyOfRange(in, inOfs, inOfs + len));
+ doLastBlock(in, inOfs, len, out, outOfs, true);
+ }
+
+ byte[] lengthBlock = getLengthBlock(sizeOfAAD*8, processed*8);
+ ghashAllToS.update(lengthBlock);
+ byte[] s = ghashAllToS.digest();
+ byte[] sOut = new byte[s.length];
+ GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock);
+ gctrForSToTag.doFinal(s, 0, s.length, sOut, 0);
+
+ System.arraycopy(sOut, 0, out, (outOfs + len), tagLenBytes);
+ return (len + tagLenBytes);
+ }
+
+ /**
+ * Performs decryption operation.
+ *
+ *
The input cipher text in
, starting at
+ * inOfs
and ending at (inOfs + len - 1)
,
+ * is decrypted. The result is stored in out
, starting at
+ * outOfs
.
+ *
+ *
It is the application's responsibility to make sure that
+ * len
is a multiple of the embedded cipher's block
+ * size, as any excess bytes are ignored.
+ *
+ *
It is also the application's responsibility to make sure that
+ * init
has been called before this method is called.
+ * (This check is omitted here, to avoid double checking.)
+ *
+ * @param in the buffer with the input data to be decrypted
+ * @param inOfs the offset in in
+ * @param len the length of the input data
+ * @param out the buffer for the result
+ * @param outOfs the offset in out
+ */
+ void decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
+ processAAD();
+
+ if (len > 0) { // must be at least AES_BLOCK_SIZE bytes long
+ gctrPAndC.update(in, inOfs, len, out, outOfs);
+ processed += len;
+ ghashAllToS.update(in, inOfs, len);
+ }
+ }
+
+ /**
+ * Performs decryption operation for the last time.
+ *
+ *
NOTE: For cipher feedback modes which does not perform
+ * special handling for the last few blocks, this is essentially
+ * the same as encrypt(...)
. Given most modes do
+ * not do special handling, the default impl for this method is
+ * to simply call decrypt(...)
.
+ *
+ * @param in the input buffer with the data to be decrypted
+ * @param inOfs the offset in cipher
+ * @param len the length of the input data
+ * @param out the buffer for the decryption result
+ * @param outOfs the offset in plain
+ * @return the number of bytes placed into the out
buffer
+ */
+ int decryptFinal(byte[] in, int inOfs, int len,
+ byte[] out, int outOfs)
+ throws IllegalBlockSizeException, AEADBadTagException {
+ if (len < tagLenBytes) {
+ throw new RuntimeException("Input buffer too short - need tag");
+ }
+ if (out.length - outOfs < (len - tagLenBytes)) {
+ throw new RuntimeException("Output buffer too small");
+ }
+ processAAD();
+
+ int processedOld = processed;
+ byte[] tag = new byte[tagLenBytes];
+ // get the trailing tag bytes from 'in'
+ System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes);
+ len -= tagLenBytes;
+
+ if (len > 0) {
+ doLastBlock(in, inOfs, len, out, outOfs, false);
+ }
+
+ byte[] lengthBlock = getLengthBlock(sizeOfAAD*8, processed*8);
+ ghashAllToS.update(lengthBlock);
+
+ byte[] s = ghashAllToS.digest();
+ byte[] sOut = new byte[s.length];
+ GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock);
+ gctrForSToTag.doFinal(s, 0, s.length, sOut, 0);
+ for (int i = 0; i < tagLenBytes; i++) {
+ if (tag[i] != sOut[i]) {
+ throw new AEADBadTagException("Tag mismatch!");
+ }
+ }
+ return len;
+ }
+
+ // return tag length in bytes
+ int getTagLen() {
+ return this.tagLenBytes;
+ }
+}
diff --git a/src/share/classes/com/sun/crypto/provider/HmacMD5KeyGenerator.java b/src/share/classes/com/sun/crypto/provider/HmacMD5KeyGenerator.java
index 46cc4ce080c3d1366e708aeaa316f67220626bbd..8482db8f9a840fee863354a3dd0d73045d4e6587 100644
--- a/src/share/classes/com/sun/crypto/provider/HmacMD5KeyGenerator.java
+++ b/src/share/classes/com/sun/crypto/provider/HmacMD5KeyGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,7 @@ public final class HmacMD5KeyGenerator extends KeyGeneratorSpi {
*/
protected SecretKey engineGenerateKey() {
if (this.random == null) {
- this.random = SunJCE.RANDOM;
+ this.random = SunJCE.getRandom();
}
byte[] keyBytes = new byte[this.keysize];
diff --git a/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java b/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java
index ef0ef58ee45a43544b0a2aa5ccedb3f1a8a7e26c..d41b88c7e38fbc8c37c6d9cd20c1558b9bd93c42 100644
--- a/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java
+++ b/src/share/classes/com/sun/crypto/provider/HmacPKCS12PBESHA1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -89,7 +89,7 @@ public final class HmacPKCS12PBESHA1 extends HmacCore {
// generate default for salt and iteration count if necessary
if (salt == null) {
salt = new byte[20];
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
}
if (iCount == 0) iCount = 100;
} else if (!(params instanceof PBEParameterSpec)) {
diff --git a/src/share/classes/com/sun/crypto/provider/HmacSHA1KeyGenerator.java b/src/share/classes/com/sun/crypto/provider/HmacSHA1KeyGenerator.java
index 02f3554f2ab8892af596a4feb2f6e68fdefc1c2a..7a29af3889de545d73a569c7c7a92fd080cacd69 100644
--- a/src/share/classes/com/sun/crypto/provider/HmacSHA1KeyGenerator.java
+++ b/src/share/classes/com/sun/crypto/provider/HmacSHA1KeyGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,7 @@ public final class HmacSHA1KeyGenerator extends KeyGeneratorSpi {
*/
protected SecretKey engineGenerateKey() {
if (this.random == null) {
- this.random = SunJCE.RANDOM;
+ this.random = SunJCE.getRandom();
}
byte[] keyBytes = new byte[this.keysize];
diff --git a/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java b/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java
index 9b850c67d87d58ff29bda0e2e34dbb8adff495cc..7377fab0a9c114ed19b26648cf95a423b9ecfd7a 100644
--- a/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java
+++ b/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@ final class ISO10126Padding implements Padding {
byte paddingOctet = (byte) (len & 0xff);
byte[] padding = new byte[len];
- SunJCE.RANDOM.nextBytes(padding);
+ SunJCE.getRandom().nextBytes(padding);
padding[len-1] = paddingOctet;
System.arraycopy(padding, 0, in, off, len);
return;
diff --git a/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java b/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java
index 9593bbfe0b0012a233ee2478579a9df9052a85d1..a5fd638da5b47177fd7e83897ef80770fd8bce8a 100644
--- a/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java
+++ b/src/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,7 @@ final class KeyGeneratorCore {
// generate the key
SecretKey implGenerateKey() {
if (random == null) {
- random = SunJCE.RANDOM;
+ random = SunJCE.getRandom();
}
byte[] b = new byte[(keySize + 7) >> 3];
random.nextBytes(b);
diff --git a/src/share/classes/com/sun/crypto/provider/KeyProtector.java b/src/share/classes/com/sun/crypto/provider/KeyProtector.java
index e30f90c1b6e0108940c67afd519feae263f49a65..0129d3d3f1015d6c95a5e0434cf48fde31e80564 100644
--- a/src/share/classes/com/sun/crypto/provider/KeyProtector.java
+++ b/src/share/classes/com/sun/crypto/provider/KeyProtector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -99,7 +99,7 @@ final class KeyProtector {
{
// create a random salt (8 bytes)
byte[] salt = new byte[8];
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
// create PBE parameters from salt and iteration count
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20);
@@ -284,7 +284,7 @@ final class KeyProtector {
{
// create a random salt (8 bytes)
byte[] salt = new byte[8];
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
// create PBE parameters from salt and iteration count
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20);
diff --git a/src/share/classes/com/sun/crypto/provider/PBECipherCore.java b/src/share/classes/com/sun/crypto/provider/PBECipherCore.java
index 7181ceeddbf6ab040f592e1f96789b00bc2b4875..c1fb9ccb7f83d02459149e927b7e9d0d1798b5b5 100644
--- a/src/share/classes/com/sun/crypto/provider/PBECipherCore.java
+++ b/src/share/classes/com/sun/crypto/provider/PBECipherCore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -164,7 +164,7 @@ final class PBECipherCore {
AlgorithmParameters params = null;
if (salt == null) {
salt = new byte[8];
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
}
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
try {
diff --git a/src/share/classes/com/sun/crypto/provider/PBES1Core.java b/src/share/classes/com/sun/crypto/provider/PBES1Core.java
index 1e206a2dd661637b38861da65f6b9b81f1bdaf4d..4199173b9f096023b2a4c83dd043780b1b8971a5 100644
--- a/src/share/classes/com/sun/crypto/provider/PBES1Core.java
+++ b/src/share/classes/com/sun/crypto/provider/PBES1Core.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -164,7 +164,7 @@ final class PBES1Core {
AlgorithmParameters params = null;
if (salt == null) {
salt = new byte[8];
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
}
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
try {
diff --git a/src/share/classes/com/sun/crypto/provider/PBES2Core.java b/src/share/classes/com/sun/crypto/provider/PBES2Core.java
index 4e5eb8e6dd18a14938b3c45c0f1293b8c437bdd0..4e61e1fae8dfc6892cb37b319015846c1af4350d 100644
--- a/src/share/classes/com/sun/crypto/provider/PBES2Core.java
+++ b/src/share/classes/com/sun/crypto/provider/PBES2Core.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -134,13 +134,13 @@ abstract class PBES2Core extends CipherSpi {
if (salt == null) {
// generate random salt and use default iteration count
salt = new byte[DEFAULT_SALT_LENGTH];
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
iCount = DEFAULT_COUNT;
}
if (ivSpec == null) {
// generate random IV
byte[] ivBytes = new byte[blkSize];
- SunJCE.RANDOM.nextBytes(ivBytes);
+ SunJCE.getRandom().nextBytes(ivBytes);
ivSpec = new IvParameterSpec(ivBytes);
}
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec);
diff --git a/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java b/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java
index fef4eda8a8b935170ad1c865e5282deff7761b03..47663943184278c0e21e30c2ca60204433c5fae2 100644
--- a/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java
+++ b/src/share/classes/com/sun/crypto/provider/PBMAC1Core.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -123,7 +123,7 @@ abstract class PBMAC1Core extends HmacCore {
// generate default for salt and iteration count if necessary
if (salt == null) {
salt = new byte[DEFAULT_SALT_LENGTH];
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
}
if (iCount == 0) iCount = DEFAULT_COUNT;
} else if (!(params instanceof PBEParameterSpec)) {
diff --git a/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java b/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java
index 45f1c304d678de2a003db31cddf87642014568a2..c76603a95de2660848ba34d072cb26367774f0c8 100644
--- a/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java
+++ b/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -227,7 +227,7 @@ final class PKCS12PBECipherCore {
// follow the recommendation in PKCS12 v1.0
// section B.4 to generate salt and iCount.
salt = new byte[DEFAULT_SALT_LENGTH];
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
iCount = DEFAULT_COUNT;
}
PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
@@ -294,7 +294,7 @@ final class PKCS12PBECipherCore {
if (random != null) {
random.nextBytes(salt);
} else {
- SunJCE.RANDOM.nextBytes(salt);
+ SunJCE.getRandom().nextBytes(salt);
}
}
if (iCount == 0) iCount = DEFAULT_COUNT;
diff --git a/src/share/classes/com/sun/crypto/provider/SunJCE.java b/src/share/classes/com/sun/crypto/provider/SunJCE.java
index 3edac42c6badc2931a3f6d0a1acc96671ccc0f98..99a2a30ab52f53d99c31511ac1cb8e6c0531fe81 100644
--- a/src/share/classes/com/sun/crypto/provider/SunJCE.java
+++ b/src/share/classes/com/sun/crypto/provider/SunJCE.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,7 @@ import java.security.SecureRandom;
* - ARCFOUR (RC4 compatible)
*
* - Cipher modes ECB, CBC, CFB, OFB, PCBC, CTR, and CTS for all block ciphers
+ * and mode GCM for AES cipher
*
* - Cipher padding ISO10126Padding for non-PKCS#5 block ciphers and
* NoPadding and PKCS5Padding for all block ciphers
@@ -90,7 +91,12 @@ public final class SunJCE extends Provider {
/* Are we debugging? -- for developers */
static final boolean debug = false;
- static final SecureRandom RANDOM = new SecureRandom();
+ // lazy initialize SecureRandom to avoid potential recursion if Sun
+ // provider has not been installed yet
+ private static class SecureRandomHolder {
+ static final SecureRandom RANDOM = new SecureRandom();
+ }
+ static SecureRandom getRandom() { return SecureRandomHolder.RANDOM; }
public SunJCE() {
/* We are the "SunJCE" provider */
@@ -100,7 +106,7 @@ public final class SunJCE extends Provider {
"|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" +
"|OFB8|OFB16|OFB24|OFB32|OFB40|OFB48|OFB56|OFB64";
final String BLOCK_MODES128 = BLOCK_MODES +
- "|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128" +
+ "|GCM|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128" +
"|OFB72|OFB80|OFB88|OFB96|OFB104|OFB112|OFB120|OFB128";
final String BLOCK_PADS = "NOPADDING|PKCS5PADDING|ISO10126PADDING";
@@ -258,6 +264,9 @@ public final class SunJCE extends Provider {
put("Cipher.AES_128/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_CFB_NoPadding");
put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding");
put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding");
+ put("Cipher.AES_128/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES128_GCM_NoPadding");
+ put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.6", "AES_128/GCM/NoPadding");
+ put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.6", "AES_128/GCM/NoPadding");
put("Cipher.AES_192/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_ECB_NoPadding");
put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.21", "AES_192/ECB/NoPadding");
@@ -271,7 +280,9 @@ public final class SunJCE extends Provider {
put("Cipher.AES_192/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_CFB_NoPadding");
put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding");
put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding");
-
+ put("Cipher.AES_192/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES192_GCM_NoPadding");
+ put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.26", "AES_192/GCM/NoPadding");
+ put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.26", "AES_192/GCM/NoPadding");
put("Cipher.AES_256/ECB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_ECB_NoPadding");
put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.41", "AES_256/ECB/NoPadding");
@@ -285,6 +296,9 @@ public final class SunJCE extends Provider {
put("Cipher.AES_256/CFB/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_CFB_NoPadding");
put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding");
put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding");
+ put("Cipher.AES_256/GCM/NoPadding", "com.sun.crypto.provider.AESCipher$AES256_GCM_NoPadding");
+ put("Alg.Alias.Cipher.2.16.840.1.101.3.4.1.46", "AES_256/GCM/NoPadding");
+ put("Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.46", "AES_256/GCM/NoPadding");
put("Cipher.AESWrap", "com.sun.crypto.provider.AESWrapCipher$General");
put("Cipher.AESWrap SupportedModes", "ECB");
@@ -509,6 +523,8 @@ public final class SunJCE extends Provider {
put("AlgorithmParameters.AES",
"com.sun.crypto.provider.AESParameters");
put("Alg.Alias.AlgorithmParameters.Rijndael", "AES");
+ put("AlgorithmParameters.GCM",
+ "com.sun.crypto.provider.GCMParameters");
put("AlgorithmParameters.RC2",
diff --git a/src/share/classes/java/lang/AbstractStringBuilder.java b/src/share/classes/java/lang/AbstractStringBuilder.java
index fc513f55efe961811fabcccd4f9de270beb0184f..03999c445a55d0810a50e57ab9d460e03c9effe2 100644
--- a/src/share/classes/java/lang/AbstractStringBuilder.java
+++ b/src/share/classes/java/lang/AbstractStringBuilder.java
@@ -860,9 +860,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @return the specified subsequence.
*
* @throws IndexOutOfBoundsException
- * if start or end are negative,
- * if end is greater than length(),
- * or if start is greater than end
+ * if {@code start} or {@code end} are negative,
+ * if {@code end} is greater than {@code length()},
+ * or if {@code start} is greater than {@code end}
* @spec JSR-51
*/
@Override
@@ -1292,7 +1292,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* Returns the index within this string of the first occurrence of the
* specified substring, starting at the specified index. The integer
- * returned is the smallest value k for which:
+ * returned is the smallest value {@code k} for which:
*
* k >= Math.min(fromIndex, str.length()) && * this.toString().startsWith(str, k) @@ -1418,7 +1418,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { public abstract String toString(); /** - * Needed by String for the contentEquals method. + * Needed by {@code String} for the contentEquals method. */ final char[] getValue() { return value; diff --git a/src/share/classes/java/lang/FunctionalInterface.java b/src/share/classes/java/lang/FunctionalInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..0d4ae72a697666c24c06b6556109e64ef009e472 --- /dev/null +++ b/src/share/classes/java/lang/FunctionalInterface.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +import java.lang.annotation.*; + +/** + * Indicates that an interface type declaration is intended to be a + * functional interface as defined by the Java Language + * Specification. + * + * Conceptually, a functional interface has exactly one abstract + * method. Since {@linkplain java.lang.reflect.Method#isDefault() + * default methods} have an implementation, they are not abstract. If + * an interface declares an abstract method overriding one of the + * public methods of {@code java.lang.Object}, that also does + * not count toward the interface's abstract method count + * since any implementation of the interface will have an + * implementation from {@code java.lang.Object} or elsewhere. + * + *Note that instances of functional interfaces can be created with + * lambda expressions, method references, or constructor references. + * + *
If a type is annotated with this annotation type, compilers are + * required to generate an error message unless: + * + *
+ *
+ * + * @jls 4.3.2. The Class Object + * @jls 9.8 Functional Interfaces + * @jls 9.4.3 Interface Method Body + * @since 1.8 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface FunctionalInterface {} diff --git a/src/share/classes/java/lang/Integer.java b/src/share/classes/java/lang/Integer.java index 6d12f880a64492506915cf3a6921b06684cff2d4..b27f46358c50ca6de041aead05dbe8eb98214c93 100644 --- a/src/share/classes/java/lang/Integer.java +++ b/src/share/classes/java/lang/Integer.java @@ -773,7 +773,7 @@ public final class Integer extends Number implements Comparable- The type is an interface type and not an annotation type, enum, or class. + *
- The annotated type satisfies the requirements of a functional interface. + *
{ int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE - h = Math.min(i, Integer.MAX_VALUE - (-low)); + h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } high = h; diff --git a/src/share/classes/java/lang/String.java b/src/share/classes/java/lang/String.java index d73a2f7c2e9c8d4f53ad26c5a8041971ef460685..a9bc2f376481be95a1b6777f29c783b6f6c23b56 100644 --- a/src/share/classes/java/lang/String.java +++ b/src/share/classes/java/lang/String.java @@ -615,10 +615,10 @@ public final class String } /** - * Returns true if, and only if, {@link #length()} is 0. + * Returns {@code true} if, and only if, {@link #length()} is {@code 0}. * - * @return true if {@link #length()} is 0, otherwise - * false + * @return {@code true} if {@link #length()} is {@code 0}, otherwise + * {@code false} * * @since 1.6 */ @@ -1229,23 +1229,23 @@ public final class String /** * Tests if two string regions are equal. * - * A substring of this String object is compared to a substring + * A substring of this {@code String} object is compared to a substring * of the argument other. The result is true if these substrings * represent identical character sequences. The substring of this - * String object to be compared begins at index toffset - * and has length len. The substring of other to be compared - * begins at index ooffset and has length len. The - * result is false if and only if at least one of the following + * {@code String} object to be compared begins at index {@code toffset} + * and has length {@code len}. The substring of other to be compared + * begins at index {@code ooffset} and has length {@code len}. The + * result is {@code false} if and only if at least one of the following * is true: - *
- toffset is negative. - *
- ooffset is negative. - *
- toffset+len is greater than the length of this - * String object. - *
- ooffset+len is greater than the length of the other + *
* * @param toffset the starting offset of the subregion in this string. @@ -1280,28 +1280,28 @@ public final class String /** * Tests if two string regions are equal. *
- {@code toffset} is negative. + *
- {@code ooffset} is negative. + *
- {@code toffset+len} is greater than the length of this + * {@code String} object. + *
- {@code ooffset+len} is greater than the length of the other * argument. - *
- There is some nonnegative integer k less than len + *
- There is some nonnegative integer k less than {@code len} * such that: - * this.charAt(toffset+k) != other.charAt(ooffset+k) + *
this.charAt(toffset+k) != other.charAt(ooffset+k)
*- * A substring of this String object is compared to a substring - * of the argument other. The result is true if these + * A substring of this {@code String} object is compared to a substring + * of the argument {@code other}. The result is {@code true} if these * substrings represent character sequences that are the same, ignoring - * case if and only if ignoreCase is true. The substring of - * this String object to be compared begins at index - * toffset and has length len. The substring of - * other to be compared begins at index ooffset and - * has length len. The result is false if and only if + * case if and only if {@code ignoreCase} is true. The substring of + * this {@code String} object to be compared begins at index + * {@code toffset} and has length {@code len}. The substring of + * {@code other} to be compared begins at index {@code ooffset} and + * has length {@code len}. The result is {@code false} if and only if * at least one of the following is true: - *
- toffset is negative. - *
- ooffset is negative. - *
- toffset+len is greater than the length of this - * String object. - *
- ooffset+len is greater than the length of the other + *
- * + * * The hash value will never be zero. * * @return a hash code value for this object. diff --git a/src/share/classes/java/lang/StringBuffer.java b/src/share/classes/java/lang/StringBuffer.java index 9fabad48d68c895b14bb379413a3b1a718dfbfb5..5d7754a0cc7d104d0f451fd70c14f620bf16327f 100644 --- a/src/share/classes/java/lang/StringBuffer.java +++ b/src/share/classes/java/lang/StringBuffer.java @@ -57,7 +57,7 @@ package java.lang; *
- {@code toffset} is negative. + *
- {@code ooffset} is negative. + *
- {@code toffset+len} is greater than the length of this + * {@code String} object. + *
- {@code ooffset+len} is greater than the length of the other * argument. - *
- ignoreCase is false and there is some nonnegative - * integer k less than len such that: + *
- {@code ignoreCase} is {@code false} and there is some nonnegative + * integer k less than {@code len} such that: *
- ** this.charAt(toffset+k) != other.charAt(ooffset+k) *- ignoreCase is true and there is some nonnegative - * integer k less than len such that: + *
- {@code ignoreCase} is {@code true} and there is some nonnegative + * integer k less than {@code len} such that: *
* Character.toLowerCase(this.charAt(toffset+k)) != Character.toLowerCase(other.charAt(ooffset+k)) @@ -1500,12 +1500,12 @@ public final class String * of {@code ch} in the range from 0 to 0xFFFF (inclusive), * this is the smallest value k such that: ** is true. For other values of {@code ch}, it is the * smallest value k such that: *- * (this.charAt(k) == ch) && (k >= fromIndex) + * (this.charAt(k) == ch) {@code &&} (k >= fromIndex) ** is true. In either case, if no such character occurs in this * string at or after position {@code fromIndex}, then @@ -1604,12 +1604,12 @@ public final class String * from 0 to 0xFFFF (inclusive), the index returned is the largest * value k such that: *- * (this.codePointAt(k) == ch) && (k >= fromIndex) + * (this.codePointAt(k) == ch) {@code &&} (k >= fromIndex) ** is true. For other values of {@code ch}, it is the * largest value k such that: *- * (this.charAt(k) == ch) && (k <= fromIndex) + * (this.charAt(k) == ch) {@code &&} (k <= fromIndex) ** is true. In either case, if no such character occurs in this * string at or before position {@code fromIndex}, then @@ -1690,7 +1690,7 @@ public final class String * *- * (this.codePointAt(k) == ch) && (k <= fromIndex) + * (this.codePointAt(k) == ch) {@code &&} (k <= fromIndex) *The returned index is the smallest value k for which: *
* If no such value of k exists, then {@code -1} is returned. * @@ -1799,7 +1799,7 @@ public final class String * *- * k >= fromIndex && this.startsWith(str, k) + * k >= fromIndex {@code &&} this.startsWith(str, k) *The returned index is the largest value k for which: *
* If no such value of k exists, then {@code -1} is returned. * @@ -2080,17 +2080,18 @@ public final class String * href="../util/regex/Pattern.html#sum">regular expression. * *- * k <= fromIndex && this.startsWith(str, k) + * k {@code <=} fromIndex {@code &&} this.startsWith(str, k) *An invocation of this method of the form - * str.matches(regex) yields exactly the + * str{@code .matches(}regex{@code )} yields exactly the * same result as the expression * - *
{@link java.util.regex.Pattern}.{@link - * java.util.regex.Pattern#matches(String,CharSequence) - * matches}(regex, str)+ *+ * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#matches(String,CharSequence) + * matches(regex, str)} + ** * @param regex * the regular expression to which this string is to be matched * - * @return true if, and only if, this string matches the + * @return {@code true} if, and only if, this string matches the * given regular expression * * @throws PatternSyntaxException @@ -2124,18 +2125,20 @@ public final class String * given replacement. * *An invocation of this method of the form - * str.replaceFirst(regex, repl) + * str{@code .replaceFirst(}regex{@code ,} repl{@code )} * yields exactly the same result as the expression * - *
- * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile - * compile}(regex).{@link - * java.util.regex.Pattern#matcher(java.lang.CharSequence) - * matcher}(str).{@link java.util.regex.Matcher#replaceFirst - * replaceFirst}(repl)+ *+ ** *+ * {@link java.util.regex.Pattern}.{@link + * java.util.regex.Pattern#compile compile}(regex).{@link + * java.util.regex.Pattern#matcher(java.lang.CharSequence) matcher}(str).{@link + * java.util.regex.Matcher#replaceFirst replaceFirst}(repl) + *
+ *- * Note that backslashes (\) and dollar signs ($) in the + * Note that backslashes ({@code \}) and dollar signs ({@code $}) in the * replacement string may cause the results to be different than if it were * being treated as a literal replacement string; see * {@link java.util.regex.Matcher#replaceFirst}. @@ -2147,7 +2150,7 @@ public final class String * @param replacement * the string to be substituted for the first match * - * @return The resulting String + * @return The resulting {@code String} * * @throws PatternSyntaxException * if the regular expression's syntax is invalid @@ -2167,18 +2170,20 @@ public final class String * given replacement. * *
An invocation of this method of the form - * str.replaceAll(regex, repl) + * str{@code .replaceAll(}regex{@code ,} repl{@code )} * yields exactly the same result as the expression * - *
- * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile - * compile}(regex).{@link - * java.util.regex.Pattern#matcher(java.lang.CharSequence) - * matcher}(str).{@link java.util.regex.Matcher#replaceAll - * replaceAll}(repl)+ *+ ** *+ * {@link java.util.regex.Pattern}.{@link + * java.util.regex.Pattern#compile compile}(regex).{@link + * java.util.regex.Pattern#matcher(java.lang.CharSequence) matcher}(str).{@link + * java.util.regex.Matcher#replaceAll replaceAll}(repl) + *
+ *- * Note that backslashes (\) and dollar signs ($) in the + * Note that backslashes ({@code \}) and dollar signs ({@code $}) in the * replacement string may cause the results to be different than if it were * being treated as a literal replacement string; see * {@link java.util.regex.Matcher#replaceAll Matcher.replaceAll}. @@ -2190,7 +2195,7 @@ public final class String * @param replacement * the string to be substituted for each match * - * @return The resulting String + * @return The resulting {@code String} * * @throws PatternSyntaxException * if the regular expression's syntax is invalid @@ -2234,7 +2239,7 @@ public final class String * expression does not match any part of the input then the resulting array * has just one element, namely this string. * - *
The limit parameter controls the number of times the + *
The {@code limit} parameter controls the number of times the * pattern is applied and therefore affects the length of the resulting * array. If the limit n is greater than zero then the pattern * will be applied at most n - 1 times, the array's @@ -2245,7 +2250,7 @@ public final class String * the pattern will be applied as many times as possible, the array can * have any length, and trailing empty strings will be discarded. * - *
The string "boo:and:foo", for example, yields the + *
The string {@code "boo:and:foo"}, for example, yields the * following results with these parameters: * *
* *@@ -2256,33 +2261,34 @@ public final class String * *
+ * : *2 - *{ "boo", "and:foo" } {@code { "boo", "and:foo" }} *+ * : *5 - *{ "boo", "and", "foo" } {@code { "boo", "and", "foo" }} *+ * : *-2 - *{ "boo", "and", "foo" } {@code { "boo", "and", "foo" }} *+ * o *5 - *{ "b", "", ":and:f", "", "" } {@code { "b", "", ":and:f", "", "" }} *+ * o *-2 - *{ "b", "", ":and:f", "", "" } {@code { "b", "", ":and:f", "", "" }} *+ * o *0 - *{ "b", "", ":and:f" } {@code { "b", "", ":and:f" }} *An invocation of this method of the form - * str.split(regex, n) + * str.{@code split(}regex{@code ,} n{@code )} * yields the same result as the expression * *
- * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile - * compile}(regex).{@link - * java.util.regex.Pattern#split(java.lang.CharSequence,int) - * split}(str, n) + ** * @@ -2364,7 +2370,7 @@ public final class String * argument of zero. Trailing empty strings are therefore not included in * the resulting array. * - *+ * {@link java.util.regex.Pattern}.{@link + * java.util.regex.Pattern#compile compile}(regex).{@link + * java.util.regex.Pattern#split(java.lang.CharSequence,int) split}(str, n) + *
*The string "boo:and:foo", for example, yields the following + *
The string {@code "boo:and:foo"}, for example, yields the following * results with these expressions: * *
* * @@ -2815,7 +2821,7 @@ public final class String * limited by the maximum dimension of a Java array as defined by * The Java™ Virtual Machine Specification. * The behaviour on a - * null argument depends on the conversion. * * @throws java.util.IllegalFormatException @@ -2828,7 +2834,7 @@ public final class String * formatter class specification. * * @throws NullPointerException - * If the format is null + * If the {@code format} is {@code null} * * @return A formatted string * @@ -2845,7 +2851,7 @@ public final class String * * @param l * The {@linkplain java.util.Locale locale} to apply during - * formatting. If l is null then no localization + * formatting. If {@code l} is {@code null} then no localization * is applied. * * @param format @@ -2859,7 +2865,7 @@ public final class String * limited by the maximum dimension of a Java array as defined by * The Java™ Virtual Machine Specification. * The behaviour on a - * null argument depends on the conversion. * * @throws java.util.IllegalFormatException @@ -2872,7 +2878,7 @@ public final class String * formatter class specification * * @throws NullPointerException - * If the format is null + * If the {@code format} is {@code null} * * @return A formatted string * @@ -3143,7 +3149,7 @@ public final class String * programmer should be aware that producing distinct integer results * for unequal objects may improve the performance of hash tables. *@@ -2373,9 +2379,9 @@ public final class String *
Result * *+ * : - *{ "boo", "and", "foo" } {@code { "boo", "and", "foo" }} *+ * o - *{ "b", "", ":and:f" } {@code { "b", "", ":and:f" }} ** In general, if sb refers to an instance of a {@code StringBuffer}, * then {@code sb.append(x)} has the same effect as - * {@code sb.insert(sb.length(), x)}. + * {@code sb.insert(sb.length(), x)}. *
* Whenever an operation occurs involving a source sequence (such as * appending or inserting from a source sequence), this class synchronizes @@ -80,7 +80,7 @@ package java.lang; * * As of release JDK 5, this class has been supplemented with an equivalent * class designed for use by a single thread, {@link StringBuilder}. The - * StringBuilder class should generally be used in preference to + * {@code StringBuilder} class should generally be used in preference to * this one, as it supports all of the same operations but it is faster, as * it performs no synchronization. * @@ -262,17 +262,17 @@ package java.lang; } /** - * Appends the specified StringBuffer to this sequence. + * Appends the specified {@code StringBuffer} to this sequence. *
- * The characters of the StringBuffer argument are appended, - * in order, to the contents of this StringBuffer, increasing the - * length of this StringBuffer by the length of the argument. - * If sb is null, then the four characters - * "null" are appended to this StringBuffer. + * The characters of the {@code StringBuffer} argument are appended, + * in order, to the contents of this {@code StringBuffer}, increasing the + * length of this {@code StringBuffer} by the length of the argument. + * If {@code sb} is {@code null}, then the four characters + * {@code "null"} are appended to this {@code StringBuffer}. *
* Let n be the length of the old character sequence, the one - * contained in the StringBuffer just prior to execution of the - * append method. Then the character at index k in + * contained in the {@code StringBuffer} just prior to execution of the + * {@code append} method. Then the character at index k in * the new character sequence is equal to the character at index k * in the old character sequence, if k is less than n; * otherwise, it is equal to the character at index k-n in the @@ -281,7 +281,7 @@ package java.lang; * This method synchronizes on {@code this}, the destination * object, but does not synchronize on the source ({@code sb}). * - * @param sb the StringBuffer to append. + * @param sb the {@code StringBuffer} to append. * @return a reference to this object. * @since 1.4 */ diff --git a/src/share/classes/java/lang/StringBuilder.java b/src/share/classes/java/lang/StringBuilder.java index acddd83a8a30983b8c3e578f5155f02146cff8bb..e9defe23f6f7c7a31e153ce17bbf46f10e167297 100644 --- a/src/share/classes/java/lang/StringBuilder.java +++ b/src/share/classes/java/lang/StringBuilder.java @@ -28,39 +28,39 @@ package java.lang; /** * A mutable sequence of characters. This class provides an API compatible - * with
StringBuffer
, but with no guarantee of synchronization. + * with {@code StringBuffer}, but with no guarantee of synchronization. * This class is designed for use as a drop-in replacement for - *StringBuffer
in places where the string buffer was being + * {@code StringBuffer} in places where the string buffer was being * used by a single thread (as is generally the case). Where possible, * it is recommended that this class be used in preference to - *StringBuffer
as it will be faster under most implementations. + * {@code StringBuffer} as it will be faster under most implementations. * - *The principal operations on a
StringBuilder
are the - *append
andinsert
methods, which are + *The principal operations on a {@code StringBuilder} are the + * {@code append} and {@code insert} methods, which are * overloaded so as to accept data of any type. Each effectively * converts a given datum to a string and then appends or inserts the * characters of that string to the string builder. The - *
append
method always adds these characters at the end - * of the builder; theinsert
method adds the characters at + * {@code append} method always adds these characters at the end + * of the builder; the {@code insert} method adds the characters at * a specified point. *- * For example, if
z
refers to a string builder object - * whose current contents are "start
", then - * the method callz.append("le")
would cause the string - * builder to contain "startle
", whereas - *z.insert(4, "le")
would alter the string builder to - * contain "starlet
". + * For example, if {@code z} refers to a string builder object + * whose current contents are "{@code start}", then + * the method call {@code z.append("le")} would cause the string + * builder to contain "{@code startle}", whereas + * {@code z.insert(4, "le")} would alter the string builder to + * contain "{@code starlet}". + *+ * In general, if sb refers to an instance of a {@code StringBuilder}, + * then {@code sb.append(x)} has the same effect as + * {@code sb.insert(sb.length(), x)}. *
- * In general, if sb refers to an instance of a
StringBuilder
, - * thensb.append(x)
has the same effect as - *sb.insert(sb.length(), x)
. - * * Every string builder has a capacity. As long as the length of the * character sequence contained in the string builder does not exceed * the capacity, it is not necessary to allocate a new internal * buffer. If the internal buffer overflows, it is automatically made larger. * - *Instances of
StringBuilder
are not safe for + *Instances of {@code StringBuilder} are not safe for * use by multiple threads. If such synchronization is required then it is * recommended that {@link java.lang.StringBuffer} be used. * @@ -87,11 +87,11 @@ public final class StringBuilder /** * Constructs a string builder with no characters in it and an - * initial capacity specified by the
capacity
argument. + * initial capacity specified by the {@code capacity} argument. * * @param capacity the initial capacity. - * @throws NegativeArraySizeException if thecapacity
- * argument is less than0
. + * @throws NegativeArraySizeException if the {@code capacity} + * argument is less than {@code 0}. */ public StringBuilder(int capacity) { super(capacity); @@ -100,10 +100,10 @@ public final class StringBuilder /** * Constructs a string builder initialized to the contents of the * specified string. The initial capacity of the string builder is - *16
plus the length of the string argument. + * {@code 16} plus the length of the string argument. * * @param str the initial contents of the buffer. - * @throws NullPointerException ifstr
isnull
+ * @throws NullPointerException if {@code str} is {@code null} */ public StringBuilder(String str) { super(str.length() + 16); @@ -112,12 +112,12 @@ public final class StringBuilder /** * Constructs a string builder that contains the same characters - * as the specifiedCharSequence
. The initial capacity of - * the string builder is16
plus the length of the - *CharSequence
argument. + * as the specified {@code CharSequence}. The initial capacity of + * the string builder is {@code 16} plus the length of the + * {@code CharSequence} argument. * * @param seq the sequence to copy. - * @throws NullPointerException ifseq
isnull
+ * @throws NullPointerException if {@code seq} is {@code null} */ public StringBuilder(CharSequence seq) { this(seq.length() + 16); @@ -136,22 +136,22 @@ public final class StringBuilder } /** - * Appends the specified StringBuffer to this sequence. + * Appends the specified {@code StringBuffer} to this sequence. *- * The characters of the StringBuffer argument are appended, + * The characters of the {@code StringBuffer} argument are appended, * in order, to this sequence, increasing the * length of this sequence by the length of the argument. - * If sb is null, then the four characters - * "null" are appended to this sequence. + * If {@code sb} is {@code null}, then the four characters + * {@code "null"} are appended to this sequence. *
* Let n be the length of this character sequence just prior to - * execution of the append method. Then the character at index + * execution of the {@code append} method. Then the character at index * k in the new character sequence is equal to the character at * index k in the old character sequence, if k is less than * n; otherwise, it is equal to the character at index k-n - * in the argument
sb
. + * in the argument {@code sb}. * - * @param sb the StringBuffer to append. + * @param sb the {@code StringBuffer} to append. * @return a reference to this object. */ public StringBuilder append(StringBuffer sb) { @@ -418,13 +418,13 @@ public final class StringBuilder } /** - * Save the state of the StringBuilder instance to a stream + * Save the state of the {@code StringBuilder} instance to a stream * (that is, serialize it). * * @serialData the number of characters currently stored in the string - * builder (int), followed by the characters in the - * string builder (char[]). The length of the - * char array may be greater than the number of + * builder ({@code int}), followed by the characters in the + * string builder ({@code char[]}). The length of the + * {@code char} array may be greater than the number of * characters currently stored in the string builder, in which * case extra characters are ignored. */ diff --git a/src/share/classes/java/lang/StringIndexOutOfBoundsException.java b/src/share/classes/java/lang/StringIndexOutOfBoundsException.java index 7067e29a88c75ae5d52e5de54f69c46fec85fd72..c3aa9b7a2dfa18dd4079dc82464ba182c2d43997 100644 --- a/src/share/classes/java/lang/StringIndexOutOfBoundsException.java +++ b/src/share/classes/java/lang/StringIndexOutOfBoundsException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ package java.lang; /** - * Thrown byString
methods to indicate that an index + * Thrown by {@code String} methods to indicate that an index * is either negative or greater than the size of the string. For * some methods such as the charAt method, this exception also is * thrown when the index is equal to the size of the string. @@ -40,7 +40,7 @@ class StringIndexOutOfBoundsException extends IndexOutOfBoundsException { private static final long serialVersionUID = -6762910422159637258L; /** - * Constructs aStringIndexOutOfBoundsException
with no + * Constructs a {@code StringIndexOutOfBoundsException} with no * detail message. * * @since JDK1.0. @@ -50,7 +50,7 @@ class StringIndexOutOfBoundsException extends IndexOutOfBoundsException { } /** - * Constructs aStringIndexOutOfBoundsException
with + * Constructs a {@code StringIndexOutOfBoundsException} with * the specified detail message. * * @param s the detail message. @@ -60,7 +60,7 @@ class StringIndexOutOfBoundsException extends IndexOutOfBoundsException { } /** - * Constructs a newStringIndexOutOfBoundsException
+ * Constructs a new {@code StringIndexOutOfBoundsException} * class with an argument indicating the illegal index. * * @param index the illegal index. diff --git a/src/share/classes/java/lang/annotation/Repeatable.java b/src/share/classes/java/lang/annotation/Repeatable.java new file mode 100644 index 0000000000000000000000000000000000000000..570ed0fa5dacbe29d5c096f0364f00f9f64af253 --- /dev/null +++ b/src/share/classes/java/lang/annotation/Repeatable.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.annotation; + +/** + * The annotation type {@code java.lang.annotation.Repeatable} is + * used to indicate that the annotation type whose declaration it + * (meta-)annotates is repeatable. The value of + * {@code @Repeatable} indicates the containing annotation + * type for the repeatable annotation type. + * + * @since 1.8 + * @jls 9.6 Annotation Types + * @jls 9.7 Annotations + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface Repeatable { + /** + * Indicates the containing annotation type for the + * repeatable annotation type. + */ + Class extends Annotation> value(); +} diff --git a/src/share/classes/java/security/Principal.java b/src/share/classes/java/security/Principal.java index fb29acaa1ba71f5f99bdb9e93e0b59c97a4a7948..48938cfdd0716498338bc1d9cda3e191018b417f 100644 --- a/src/share/classes/java/security/Principal.java +++ b/src/share/classes/java/security/Principal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.security; +import javax.security.auth.Subject; + /** * This interface represents the abstract notion of a principal, which * can be used to represent any entity, such as an individual, a @@ -45,7 +47,6 @@ public interface Principal { * * @return true if the principal passed in is the same as that * encapsulated by this principal, and false otherwise. - */ public boolean equals(Object another); @@ -69,4 +70,24 @@ public interface Principal { * @return the name of this principal. */ public String getName(); + + /** + * Returns true if the specified subject is implied by this principal. + * + *The default implementation of this method returns true if + * {@code subject} is non-null and contains at least one principal that + * is equal to this principal. + * + *
Subclasses may override this with a different implementation, if + * necessary. + * + * @return true if {@code subject} is non-null and is + * implied by this principal, or false otherwise. + * @since 1.8 + */ + public default boolean implies(Subject subject) { + if (subject == null) + return false; + return subject.getPrincipals().contains(this); + } } diff --git a/src/share/classes/java/util/concurrent/ForkJoinPool.java b/src/share/classes/java/util/concurrent/ForkJoinPool.java index a8940a3ddee0eeeaa60d8aebef898bb78f637fb7..86bb3b59ebc457981fd06d258c148f6aa39456d8 100644 --- a/src/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java @@ -2611,6 +2611,7 @@ public class ForkJoinPool extends AbstractExecutorService { * {@link #shutdown} or {@link #shutdownNow}. * * @return the common pool instance + * @since 1.8 */ public static ForkJoinPool commonPool() { // assert commonPool != null : "static init error"; @@ -2793,6 +2794,7 @@ public class ForkJoinPool extends AbstractExecutorService { * Returns the targeted parallelism level of the common pool. * * @return the targeted parallelism level of the common pool + * @since 1.8 */ public static int getCommonPoolParallelism() { return commonPoolParallelism; diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicBoolean.java b/src/share/classes/java/util/concurrent/atomic/AtomicBoolean.java index a4d6d8297daa5201b97c08661e9e1b3f298482cb..04bc975f9c8c14e595b6aa1806424e4fa0033d4a 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicBoolean.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicBoolean.java @@ -111,7 +111,7 @@ public class AtomicBoolean implements java.io.Serializable { * * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public boolean weakCompareAndSet(boolean expect, boolean update) { int e = expect ? 1 : 0; @@ -146,16 +146,16 @@ public class AtomicBoolean implements java.io.Serializable { * @return the previous value */ public final boolean getAndSet(boolean newValue) { - for (;;) { - boolean current = get(); - if (compareAndSet(current, newValue)) - return current; - } + boolean prev; + do { + prev = get(); + } while (!compareAndSet(prev, newValue)); + return prev; } /** * Returns the String representation of the current value. - * @return the String representation of the current value. + * @return the String representation of the current value */ public String toString() { return Boolean.toString(get()); diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java index 0d509cda0355729e2b9f76222d5ce7801a472c75..f1c76b02bff5fb565c57fe1ef55dac07710fb714 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java @@ -115,11 +115,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the previous value */ public final int getAndSet(int newValue) { - for (;;) { - int current = get(); - if (compareAndSet(current, newValue)) - return current; - } + return unsafe.getAndSetInt(this, valueOffset, newValue); } /** @@ -145,7 +141,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public final boolean weakCompareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); @@ -157,12 +153,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the previous value */ public final int getAndIncrement() { - for (;;) { - int current = get(); - int next = current + 1; - if (compareAndSet(current, next)) - return current; - } + return getAndAdd(1); } /** @@ -171,12 +162,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the previous value */ public final int getAndDecrement() { - for (;;) { - int current = get(); - int next = current - 1; - if (compareAndSet(current, next)) - return current; - } + return getAndAdd(-1); } /** @@ -186,12 +172,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the previous value */ public final int getAndAdd(int delta) { - for (;;) { - int current = get(); - int next = current + delta; - if (compareAndSet(current, next)) - return current; - } + return unsafe.getAndAddInt(this, valueOffset, delta); } /** @@ -200,12 +181,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the updated value */ public final int incrementAndGet() { - for (;;) { - int current = get(); - int next = current + 1; - if (compareAndSet(current, next)) - return next; - } + return getAndAdd(1) + 1; } /** @@ -214,12 +190,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the updated value */ public final int decrementAndGet() { - for (;;) { - int current = get(); - int next = current - 1; - if (compareAndSet(current, next)) - return next; - } + return getAndAdd(-1) - 1; } /** @@ -229,17 +200,12 @@ public class AtomicInteger extends Number implements java.io.Serializable { * @return the updated value */ public final int addAndGet(int delta) { - for (;;) { - int current = get(); - int next = current + delta; - if (compareAndSet(current, next)) - return next; - } + return getAndAdd(delta) + delta; } /** * Returns the String representation of the current value. - * @return the String representation of the current value. + * @return the String representation of the current value */ public String toString() { return Integer.toString(get()); diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java index 9928e5974fa389eba4cd8b402e7c613fe4819da5..b5578ed93d898552c74fac304488a8f038d8a3c4 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java @@ -145,12 +145,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndSet(int i, int newValue) { - long offset = checkedByteOffset(i); - while (true) { - int current = getRaw(offset); - if (compareAndSetRaw(offset, current, newValue)) - return current; - } + return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue); } /** @@ -182,7 +177,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @param i the index * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public final boolean weakCompareAndSet(int i, int expect, int update) { return compareAndSet(i, expect, update); @@ -216,12 +211,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndAdd(int i, int delta) { - long offset = checkedByteOffset(i); - while (true) { - int current = getRaw(offset); - if (compareAndSetRaw(offset, current, current + delta)) - return current; - } + return unsafe.getAndAddInt(array, checkedByteOffset(i), delta); } /** @@ -231,7 +221,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int incrementAndGet(int i) { - return addAndGet(i, 1); + return getAndAdd(i, 1) + 1; } /** @@ -241,7 +231,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int decrementAndGet(int i) { - return addAndGet(i, -1); + return getAndAdd(i, -1) - 1; } /** @@ -252,13 +242,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int addAndGet(int i, int delta) { - long offset = checkedByteOffset(i); - while (true) { - int current = getRaw(offset); - int next = current + delta; - if (compareAndSetRaw(offset, current, next)) - return next; - } + return getAndAdd(i, delta) + delta; } /** diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index a692479ad9c0f20f9db6f333fb1972e0072d7b30..e2ae9c4f5ddced6373f78b2604eda82315c68416 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -159,11 +159,11 @@ public abstract class AtomicIntegerFieldUpdater
{ * @return the previous value */ public int getAndSet(T obj, int newValue) { - for (;;) { - int current = get(obj); - if (compareAndSet(obj, current, newValue)) - return current; - } + int prev; + do { + prev = get(obj); + } while (!compareAndSet(obj, prev, newValue)); + return prev; } /** @@ -174,12 +174,12 @@ public abstract class AtomicIntegerFieldUpdater { * @return the previous value */ public int getAndIncrement(T obj) { - for (;;) { - int current = get(obj); - int next = current + 1; - if (compareAndSet(obj, current, next)) - return current; - } + int prev, next; + do { + prev = get(obj); + next = prev + 1; + } while (!compareAndSet(obj, prev, next)); + return prev; } /** @@ -190,12 +190,12 @@ public abstract class AtomicIntegerFieldUpdater { * @return the previous value */ public int getAndDecrement(T obj) { - for (;;) { - int current = get(obj); - int next = current - 1; - if (compareAndSet(obj, current, next)) - return current; - } + int prev, next; + do { + prev = get(obj); + next = prev - 1; + } while (!compareAndSet(obj, prev, next)); + return prev; } /** @@ -207,12 +207,12 @@ public abstract class AtomicIntegerFieldUpdater { * @return the previous value */ public int getAndAdd(T obj, int delta) { - for (;;) { - int current = get(obj); - int next = current + delta; - if (compareAndSet(obj, current, next)) - return current; - } + int prev, next; + do { + prev = get(obj); + next = prev + delta; + } while (!compareAndSet(obj, prev, next)); + return prev; } /** @@ -223,12 +223,12 @@ public abstract class AtomicIntegerFieldUpdater { * @return the updated value */ public int incrementAndGet(T obj) { - for (;;) { - int current = get(obj); - int next = current + 1; - if (compareAndSet(obj, current, next)) - return next; - } + int prev, next; + do { + prev = get(obj); + next = prev + 1; + } while (!compareAndSet(obj, prev, next)); + return next; } /** @@ -239,12 +239,12 @@ public abstract class AtomicIntegerFieldUpdater { * @return the updated value */ public int decrementAndGet(T obj) { - for (;;) { - int current = get(obj); - int next = current - 1; - if (compareAndSet(obj, current, next)) - return next; - } + int prev, next; + do { + prev = get(obj); + next = prev - 1; + } while (!compareAndSet(obj, prev, next)); + return next; } /** @@ -256,12 +256,12 @@ public abstract class AtomicIntegerFieldUpdater { * @return the updated value */ public int addAndGet(T obj, int delta) { - for (;;) { - int current = get(obj); - int next = current + delta; - if (compareAndSet(obj, current, next)) - return next; - } + int prev, next; + do { + prev = get(obj); + next = prev + delta; + } while (!compareAndSet(obj, prev, next)); + return next; } /** @@ -361,6 +361,36 @@ public abstract class AtomicIntegerFieldUpdater { return unsafe.getIntVolatile(obj, offset); } + public int getAndSet(T obj, int newValue) { + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); + return unsafe.getAndSetInt(obj, offset, newValue); + } + + public int getAndIncrement(T obj) { + return getAndAdd(obj, 1); + } + + public int getAndDecrement(T obj) { + return getAndAdd(obj, -1); + } + + public int getAndAdd(T obj, int delta) { + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); + return unsafe.getAndAddInt(obj, offset, delta); + } + + public int incrementAndGet(T obj) { + return getAndAdd(obj, 1) + 1; + } + + public int decrementAndGet(T obj) { + return getAndAdd(obj, -1) - 1; + } + + public int addAndGet(T obj, int delta) { + return getAndAdd(obj, delta) + delta; + } + private void ensureProtectedAccess(T obj) { if (cclass.isInstance(obj)) { return; diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicLong.java b/src/share/classes/java/util/concurrent/atomic/AtomicLong.java index 7813aad04f4d430f9d095f64def5eaca744db06b..b38cf041fbbd54e757260cbf68188eba30df71ef 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLong.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLong.java @@ -129,11 +129,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the previous value */ public final long getAndSet(long newValue) { - while (true) { - long current = get(); - if (compareAndSet(current, newValue)) - return current; - } + return unsafe.getAndSetLong(this, valueOffset, newValue); } /** @@ -159,7 +155,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public final boolean weakCompareAndSet(long expect, long update) { return unsafe.compareAndSwapLong(this, valueOffset, expect, update); @@ -171,12 +167,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the previous value */ public final long getAndIncrement() { - while (true) { - long current = get(); - long next = current + 1; - if (compareAndSet(current, next)) - return current; - } + return getAndAdd(1); } /** @@ -185,12 +176,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the previous value */ public final long getAndDecrement() { - while (true) { - long current = get(); - long next = current - 1; - if (compareAndSet(current, next)) - return current; - } + return getAndAdd(-1); } /** @@ -200,12 +186,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the previous value */ public final long getAndAdd(long delta) { - while (true) { - long current = get(); - long next = current + delta; - if (compareAndSet(current, next)) - return current; - } + return unsafe.getAndAddLong(this, valueOffset, delta); } /** @@ -214,12 +195,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the updated value */ public final long incrementAndGet() { - for (;;) { - long current = get(); - long next = current + 1; - if (compareAndSet(current, next)) - return next; - } + return getAndAdd(1) + 1; } /** @@ -228,12 +204,7 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the updated value */ public final long decrementAndGet() { - for (;;) { - long current = get(); - long next = current - 1; - if (compareAndSet(current, next)) - return next; - } + return getAndAdd(-1) - 1; } /** @@ -243,17 +214,12 @@ public class AtomicLong extends Number implements java.io.Serializable { * @return the updated value */ public final long addAndGet(long delta) { - for (;;) { - long current = get(); - long next = current + delta; - if (compareAndSet(current, next)) - return next; - } + return getAndAdd(delta) + delta; } /** * Returns the String representation of the current value. - * @return the String representation of the current value. + * @return the String representation of the current value */ public String toString() { return Long.toString(get()); diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java index 856ab39e0c6c9f753100288497c5ab466c315eaf..9651426c7508d17169aeac49c8fc633a91c472b1 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java @@ -144,12 +144,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndSet(int i, long newValue) { - long offset = checkedByteOffset(i); - while (true) { - long current = getRaw(offset); - if (compareAndSetRaw(offset, current, newValue)) - return current; - } + return unsafe.getAndSetLong(array, checkedByteOffset(i), newValue); } /** @@ -181,7 +176,7 @@ public class AtomicLongArray implements java.io.Serializable { * @param i the index * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public final boolean weakCompareAndSet(int i, long expect, long update) { return compareAndSet(i, expect, update); @@ -215,12 +210,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndAdd(int i, long delta) { - long offset = checkedByteOffset(i); - while (true) { - long current = getRaw(offset); - if (compareAndSetRaw(offset, current, current + delta)) - return current; - } + return unsafe.getAndAddLong(array, checkedByteOffset(i), delta); } /** @@ -230,7 +220,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public final long incrementAndGet(int i) { - return addAndGet(i, 1); + return getAndAdd(i, 1) + 1; } /** @@ -240,7 +230,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public final long decrementAndGet(int i) { - return addAndGet(i, -1); + return getAndAdd(i, -1) - 1; } /** @@ -251,13 +241,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public long addAndGet(int i, long delta) { - long offset = checkedByteOffset(i); - while (true) { - long current = getRaw(offset); - long next = current + delta; - if (compareAndSetRaw(offset, current, next)) - return next; - } + return getAndAdd(i, delta) + delta; } /** diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index 8b80684d8487848a67ff9808333e2aec898d924e..a013680ce7a03eac9fef46c75c57dc25d5b1d71f 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -98,7 +98,7 @@ public abstract class AtomicLongFieldUpdater { * @param obj An object whose field to conditionally set * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful * @throws ClassCastException if {@code obj} is not an instance * of the class possessing the field established in the constructor. */ @@ -118,7 +118,7 @@ public abstract class AtomicLongFieldUpdater { * @param obj An object whose field to conditionally set * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful * @throws ClassCastException if {@code obj} is not an instance * of the class possessing the field established in the constructor. */ @@ -162,11 +162,11 @@ public abstract class AtomicLongFieldUpdater { * @return the previous value */ public long getAndSet(T obj, long newValue) { - for (;;) { - long current = get(obj); - if (compareAndSet(obj, current, newValue)) - return current; - } + long prev; + do { + prev = get(obj); + } while (!compareAndSet(obj, prev, newValue)); + return prev; } /** @@ -177,12 +177,12 @@ public abstract class AtomicLongFieldUpdater { * @return the previous value */ public long getAndIncrement(T obj) { - for (;;) { - long current = get(obj); - long next = current + 1; - if (compareAndSet(obj, current, next)) - return current; - } + long prev, next; + do { + prev = get(obj); + next = prev + 1; + } while (!compareAndSet(obj, prev, next)); + return prev; } /** @@ -193,12 +193,12 @@ public abstract class AtomicLongFieldUpdater { * @return the previous value */ public long getAndDecrement(T obj) { - for (;;) { - long current = get(obj); - long next = current - 1; - if (compareAndSet(obj, current, next)) - return current; - } + long prev, next; + do { + prev = get(obj); + next = prev - 1; + } while (!compareAndSet(obj, prev, next)); + return prev; } /** @@ -210,12 +210,12 @@ public abstract class AtomicLongFieldUpdater { * @return the previous value */ public long getAndAdd(T obj, long delta) { - for (;;) { - long current = get(obj); - long next = current + delta; - if (compareAndSet(obj, current, next)) - return current; - } + long prev, next; + do { + prev = get(obj); + next = prev + delta; + } while (!compareAndSet(obj, prev, next)); + return prev; } /** @@ -226,12 +226,12 @@ public abstract class AtomicLongFieldUpdater { * @return the updated value */ public long incrementAndGet(T obj) { - for (;;) { - long current = get(obj); - long next = current + 1; - if (compareAndSet(obj, current, next)) - return next; - } + long prev, next; + do { + prev = get(obj); + next = prev + 1; + } while (!compareAndSet(obj, prev, next)); + return next; } /** @@ -242,12 +242,12 @@ public abstract class AtomicLongFieldUpdater { * @return the updated value */ public long decrementAndGet(T obj) { - for (;;) { - long current = get(obj); - long next = current - 1; - if (compareAndSet(obj, current, next)) - return next; - } + long prev, next; + do { + prev = get(obj); + next = prev - 1; + } while (!compareAndSet(obj, prev, next)); + return next; } /** @@ -259,12 +259,12 @@ public abstract class AtomicLongFieldUpdater { * @return the updated value */ public long addAndGet(T obj, long delta) { - for (;;) { - long current = get(obj); - long next = current + delta; - if (compareAndSet(obj, current, next)) - return next; - } + long prev, next; + do { + prev = get(obj); + next = prev + delta; + } while (!compareAndSet(obj, prev, next)); + return next; } private static class CASUpdater extends AtomicLongFieldUpdater { @@ -345,6 +345,36 @@ public abstract class AtomicLongFieldUpdater { return unsafe.getLongVolatile(obj, offset); } + public long getAndSet(T obj, long newValue) { + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); + return unsafe.getAndSetLong(obj, offset, newValue); + } + + public long getAndIncrement(T obj) { + return getAndAdd(obj, 1); + } + + public long getAndDecrement(T obj) { + return getAndAdd(obj, -1); + } + + public long getAndAdd(T obj, long delta) { + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); + return unsafe.getAndAddLong(obj, offset, delta); + } + + public long incrementAndGet(T obj) { + return getAndAdd(obj, 1) + 1; + } + + public long decrementAndGet(T obj) { + return getAndAdd(obj, -1) - 1; + } + + public long addAndGet(T obj, long delta) { + return getAndAdd(obj, delta) + delta; + } + private void ensureProtectedAccess(T obj) { if (cclass.isInstance(obj)) { return; diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicReference.java b/src/share/classes/java/util/concurrent/atomic/AtomicReference.java index 8bbc25c696efa3308815c6a5a01f22622de92853..94c9edca52a65ac15e85676bf7b54c6a6c42355a 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReference.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReference.java @@ -124,7 +124,7 @@ public class AtomicReference implements java.io.Serializable { * * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public final boolean weakCompareAndSet(V expect, V update) { return unsafe.compareAndSwapObject(this, valueOffset, expect, update); @@ -136,17 +136,14 @@ public class AtomicReference implements java.io.Serializable { * @param newValue the new value * @return the previous value */ + @SuppressWarnings("unchecked") public final V getAndSet(V newValue) { - while (true) { - V x = get(); - if (compareAndSet(x, newValue)) - return x; - } + return (V)unsafe.getAndSetObject(this, valueOffset, newValue); } /** * Returns the String representation of the current value. - * @return the String representation of the current value. + * @return the String representation of the current value */ public String toString() { return String.valueOf(get()); diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index 015523ff3939128ba4b693a63afe8ed7fb1bd1ff..71308618541b39253f854fe8c9296c3c72b2dabe 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -159,13 +159,9 @@ public class AtomicReferenceArray implements java.io.Serializable { * @param newValue the new value * @return the previous value */ + @SuppressWarnings("unchecked") public final E getAndSet(int i, E newValue) { - long offset = checkedByteOffset(i); - while (true) { - E current = getRaw(offset); - if (compareAndSetRaw(offset, current, newValue)) - return current; - } + return (E)unsafe.getAndSetObject(array, checkedByteOffset(i), newValue); } /** @@ -197,7 +193,7 @@ public class AtomicReferenceArray implements java.io.Serializable { * @param i the index * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public final boolean weakCompareAndSet(int i, E expect, E update) { return compareAndSet(i, expect, update); diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index 2bb1fae40d734ba0ce9233816a47ca305805252e..78c636956f6446fcb5e6e3889adfc297a61ec55f 100644 --- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -116,7 +116,7 @@ public abstract class AtomicReferenceFieldUpdater { * @param obj An object whose field to conditionally set * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public abstract boolean compareAndSet(T obj, V expect, V update); @@ -134,7 +134,7 @@ public abstract class AtomicReferenceFieldUpdater { * @param obj An object whose field to conditionally set * @param expect the expected value * @param update the new value - * @return true if successful. + * @return true if successful */ public abstract boolean weakCompareAndSet(T obj, V expect, V update); @@ -176,11 +176,11 @@ public abstract class AtomicReferenceFieldUpdater { * @return the previous value */ public V getAndSet(T obj, V newValue) { - for (;;) { - V current = get(obj); - if (compareAndSet(obj, current, newValue)) - return current; - } + V prev; + do { + prev = get(obj); + } while (!compareAndSet(obj, prev, newValue)); + return prev; } private static final class AtomicReferenceFieldUpdaterImpl @@ -321,6 +321,15 @@ public abstract class AtomicReferenceFieldUpdater { return (V)unsafe.getObjectVolatile(obj, offset); } + @SuppressWarnings("unchecked") + public V getAndSet(T obj, V newValue) { + if (obj == null || obj.getClass() != tclass || cclass != null || + (newValue != null && vclass != null && + vclass != newValue.getClass())) + updateCheck(obj, newValue); + return (V)unsafe.getAndSetObject(obj, offset, newValue); + } + private void ensureProtectedAccess(T obj) { if (cclass.isInstance(obj)) { return; diff --git a/src/share/classes/javax/crypto/Cipher.java b/src/share/classes/javax/crypto/Cipher.java index 408d9b91172ea88793d3e907834e22bc772a7ff4..bdbe2bcd98e8291149455a86637b626b609c8db2 100644 --- a/src/share/classes/javax/crypto/Cipher.java +++ b/src/share/classes/javax/crypto/Cipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,17 +104,30 @@ import sun.security.jca.*; * must be supplied to GCM/CCM implementations (via the {@code * updateAAD} methods) before the ciphertext is processed (via * the {@code update} and {@code doFinal} methods). - * + * + * Note that GCM mode has a uniqueness requirement on IVs used in + * encryption with a given key. When IVs are repeated for GCM + * encryption, such usages are subject to forgery attacks. Thus, after + * each encryption operation using GCM mode, callers should re-initialize + * the cipher objects with GCM parameters which has a different IV value. *
- * GCMParameterSpec s = new GCMParameterSpec(...); + * GCMParameterSpec s = ...; * cipher.init(..., s); * - * // If the GCMParameterSpec is needed again - * cipher.getParameters().getParameterSpec(GCMParameterSpec.class)); + * // If the GCM parameters were generated by the provider, it can + * // be retrieved by: + * // cipher.getParameters().getParameterSpec(GCMParameterSpec.class); * * cipher.updateAAD(...); // AAD * cipher.update(...); // Multi-part update * cipher.doFinal(...); // conclusion of operation + * + * // Use a different IV value for every encryption + * byte[] newIv = ...; + * s = new GCMParameterSpec(s.getTLen(), newIv); + * cipher.init(..., s); + * ... + * ** Every implementation of the Java platform is required to support * the following standardCipher
transformations with the keysizes diff --git a/src/share/classes/javax/crypto/spec/GCMParameterSpec.java b/src/share/classes/javax/crypto/spec/GCMParameterSpec.java index 01cb1cc70284ca68e97dc445d89d257e85e37259..403205a298e82a5d095fc0448689cd3567afc923 100644 --- a/src/share/classes/javax/crypto/spec/GCMParameterSpec.java +++ b/src/share/classes/javax/crypto/spec/GCMParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ import java.security.spec.AlgorithmParameterSpec; * (Additional Authenticated Data (AAD), Keys, block ciphers, * plain/ciphertext and authentication tags) are handled in the {@code * Cipher} class. -+ *
* Please see RFC 5116 * for more information on the Authenticated Encryption with * Associated Data (AEAD) algorithm, and fxClass = FXHelper.getFXMainClass(mainClass); - if (fxClass != null) { - return fxClass; + /* + * Check if FXHelper can launch it using the FX launcher. In an FX app, + * the main class may or may not have a main method, so do this before + * validating the main class. + */ + if (mainClass.equals(FXHelper.class) || + FXHelper.doesExtendFXApplication(mainClass)) { + // Will abort() if there are problems with the FX runtime + FXHelper.setFXLaunchParameters(what, mode); + return FXHelper.class; } - // not an FX application either, abort with an error - abort(null, "java.launcher.cls.error4", mainClass.getName(), - FXHelper.JAVAFX_APPLICATION_CLASS_NAME); - return null; // avoid compiler error... + validateMainClass(mainClass); + return mainClass; } /* @@ -515,16 +521,18 @@ public enum LauncherHelper { return appClass; } - // Check for main method or return null if not found - static Method getMainMethod(Class> clazz) { + // Check the existence and signature of main and abort if incorrect + static void validateMainClass(Class> mainClass) { + Method mainMethod; try { - return clazz.getMethod("main", String[].class); - } catch (NoSuchMethodException nsme) {} - return null; - } + mainMethod = mainClass.getMethod("main", String[].class); + } catch (NoSuchMethodException nsme) { + // invalid main or not FX application, abort with an error + abort(null, "java.launcher.cls.error4", mainClass.getName(), + FXHelper.JAVAFX_APPLICATION_CLASS_NAME); + return; // Avoid compiler issues + } - // Check the signature of main and abort if it's incorrect - static void validateMainMethod(Method mainMethod) { /* * getMethod (above) will choose the correct method, based * on its name and parameter type, however, we still have to @@ -644,41 +652,78 @@ public enum LauncherHelper { } static final class FXHelper { + // Marker entry in jar manifest that designates a JavaFX application jar + private static final String JAVAFX_APPLICATION_MARKER = + "JavaFX-Application-Class"; private static final String JAVAFX_APPLICATION_CLASS_NAME = "javafx.application.Application"; private static final String JAVAFX_LAUNCHER_CLASS_NAME = "com.sun.javafx.application.LauncherImpl"; + /* + * The launch method used to invoke the JavaFX launcher. These must + * match the strings used in the launchApplication method. + * + * Command line JavaFX-App-Class Launch mode FX Launch mode + * java -cp fxapp.jar FXClass N/A LM_CLASS "LM_CLASS" + * java -cp somedir FXClass N/A LM_CLASS "LM_CLASS" + * java -jar fxapp.jar Present LM_JAR "LM_JAR" + * java -jar fxapp.jar Not Present LM_JAR "LM_JAR" + */ + private static final String JAVAFX_LAUNCH_MODE_CLASS = "LM_CLASS"; + private static final String JAVAFX_LAUNCH_MODE_JAR = "LM_JAR"; + /* * FX application launcher and launch method, so we can launch * applications with no main method. */ + private static String fxLaunchName = null; + private static String fxLaunchMode = null; + private static Class> fxLauncherClass = null; private static Method fxLauncherMethod = null; /* - * We can assume that the class does NOT have a main method or it would - * have been handled already. We do, however, need to check if the class - * extends Application and the launcher is available and abort with an - * error if it's not. + * Set the launch params according to what was passed to LauncherHelper + * so we can use the same launch mode for FX. Abort if there is any + * issue with loading the FX runtime or with the launcher method. */ - private static Class> getFXMainClass(Class> mainClass) { - // Check if mainClass extends Application - if (!doesExtendFXApplication(mainClass)) { - return null; - } - + private static void setFXLaunchParameters(String what, int mode) { // Check for the FX launcher classes try { fxLauncherClass = scloader.loadClass(JAVAFX_LAUNCHER_CLASS_NAME); + /* + * signature must be: + * public static void launchApplication(String launchName, + * String launchMode, String[] args); + */ fxLauncherMethod = fxLauncherClass.getMethod("launchApplication", - Class.class, String[].class); + String.class, String.class, String[].class); + + // verify launcher signature as we do when validating the main method + int mod = fxLauncherMethod.getModifiers(); + if (!Modifier.isStatic(mod)) { + abort(null, "java.launcher.javafx.error1"); + } + if (fxLauncherMethod.getReturnType() != java.lang.Void.TYPE) { + abort(null, "java.launcher.javafx.error1"); + } } catch (ClassNotFoundException | NoSuchMethodException ex) { abort(ex, "java.launcher.cls.error5", ex); } - // That's all, return this class so we can launch later - return FXHelper.class; + fxLaunchName = what; + switch (mode) { + case LM_CLASS: + fxLaunchMode = JAVAFX_LAUNCH_MODE_CLASS; + break; + case LM_JAR: + fxLaunchMode = JAVAFX_LAUNCH_MODE_JAR; + break; + default: + // should not have gotten this far... + throw new InternalError(mode + ": Unknown launch mode"); + } } /* @@ -696,11 +741,15 @@ public enum LauncherHelper { return false; } - // preloader ? public static void main(String... args) throws Exception { + if (fxLauncherMethod == null + || fxLaunchMode == null + || fxLaunchName == null) { + throw new RuntimeException("Invalid JavaFX launch parameters"); + } // launch appClass via fxLauncherMethod - fxLauncherMethod.invoke(null, new Object[] {appClass, args}); + fxLauncherMethod.invoke(null, + new Object[] {fxLaunchName, fxLaunchMode, args}); } } } - diff --git a/src/share/classes/sun/launcher/resources/launcher.properties b/src/share/classes/sun/launcher/resources/launcher.properties index bfa05181784b22faec62b605079c4ebf34684704..8fbefacf8da73e5350fdd97223654cdf83314a63 100644 --- a/src/share/classes/sun/launcher/resources/launcher.properties +++ b/src/share/classes/sun/launcher/resources/launcher.properties @@ -140,3 +140,6 @@ java.launcher.jar.error1=\ java.launcher.jar.error2=manifest not found in {0} java.launcher.jar.error3=no main manifest attribute, in {0} java.launcher.init.error=initialization error +java.launcher.javafx.error1=\ + Error: The JavaFX launchApplication method has the wrong signature, it\n\ + must be declared static and return a value of type void diff --git a/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java b/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java index 390898292f0cb6f82de621e19862992ee494757b..41f55998973d9f0d693a01db2cde60c150ab2d92 100644 --- a/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java +++ b/src/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java @@ -206,7 +206,8 @@ public class AuthenticationHeader { if(v == null) { if ((v=schemes.get ("digest")) == null) { - if (((v=schemes.get("ntlm"))==null)) { + if (!NTLMAuthenticationProxy.supported + || ((v=schemes.get("ntlm"))==null)) { v = schemes.get ("basic"); } } diff --git a/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java b/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java index edd4bcf7c4514e98e96e015ce65d2640f338add4..ff2154ffce015183683acadabd8768fbe771dbe7 100644 --- a/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java +++ b/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java @@ -86,7 +86,7 @@ class InitSecContextToken extends InitialToken { * For the context acceptor to call. It reads the bytes out of an * InputStream and constructs an InitSecContextToken with them. */ - InitSecContextToken(Krb5Context context, EncryptionKey[] keys, + InitSecContextToken(Krb5Context context, Krb5AcceptCredential cred, InputStream is) throws IOException, GSSException, KrbException { @@ -105,7 +105,7 @@ class InitSecContextToken extends InitialToken { if (context.getChannelBinding() != null) { addr = context.getChannelBinding().getInitiatorAddress(); } - apReq = new KrbApReq(apReqBytes, keys, addr); + apReq = new KrbApReq(apReqBytes, cred, addr); //debug("\nReceived AP-REQ and authenticated it.\n"); EncryptionKey sessionKey = apReq.getCreds().getSessionKey(); diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java b/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java index 0f65137cecfacfb0056e97586e03e39a87037672..4a4d0fca89c94e23551207e4b817582d9cda6c43 100644 --- a/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java +++ b/src/share/classes/sun/security/jgss/krb5/Krb5AcceptCredential.java @@ -45,13 +45,10 @@ import javax.security.auth.DestroyFailedException; public class Krb5AcceptCredential implements Krb5CredElement { - private static final long serialVersionUID = 7714332137352567952L; + private final Krb5NameElement name; + private final ServiceCreds screds; - private Krb5NameElement name; - - private Krb5Util.ServiceCreds screds; - - private Krb5AcceptCredential(Krb5NameElement name, Krb5Util.ServiceCreds creds) { + private Krb5AcceptCredential(Krb5NameElement name, ServiceCreds creds) { /* * Initialize this instance with the data from the acquired * KerberosKey. This class needs to be a KerberosKey too @@ -69,11 +66,11 @@ public class Krb5AcceptCredential name.getKrb5PrincipalName().getName()); final AccessControlContext acc = AccessController.getContext(); - Krb5Util.ServiceCreds creds = null; + ServiceCreds creds = null; try { creds = AccessController.doPrivileged( - new PrivilegedExceptionAction
() { - public Krb5Util.ServiceCreds run() throws Exception { + new PrivilegedExceptionAction () { + public ServiceCreds run() throws Exception { return Krb5Util.getServiceCreds( caller == GSSCaller.CALLER_UNKNOWN ? GSSCaller.CALLER_ACCEPT: caller, serverPrinc, acc); @@ -92,8 +89,10 @@ public class Krb5AcceptCredential if (name == null) { String fullName = creds.getName(); - name = Krb5NameElement.getInstance(fullName, + if (fullName != null) { + name = Krb5NameElement.getInstance(fullName, Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL); + } } return new Krb5AcceptCredential(name, creds); @@ -153,8 +152,8 @@ public class Krb5AcceptCredential return Krb5MechFactory.PROVIDER; } - EncryptionKey[] getKrb5EncryptionKeys() { - return screds.getEKeys(); + public EncryptionKey[] getKrb5EncryptionKeys(PrincipalName princ) { + return screds.getEKeys(princ); } /** diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5Context.java b/src/share/classes/sun/security/jgss/krb5/Krb5Context.java index be8074097c9cc353ca28039aeb323bcc389c8d4b..309c1814bf3ae9e5a9a52c72bdd7fd65976d1946 100644 --- a/src/share/classes/sun/security/jgss/krb5/Krb5Context.java +++ b/src/share/classes/sun/security/jgss/krb5/Krb5Context.java @@ -818,16 +818,23 @@ class Krb5Context implements GSSContextSpi { } myName = (Krb5NameElement) myCred.getName(); - checkPermission(myName.getKrb5PrincipalName().getName(), - "accept"); - - EncryptionKey[] secretKeys = - ((Krb5AcceptCredential) myCred).getKrb5EncryptionKeys(); + // If there is already a bound name, check now + if (myName != null) { + Krb5MechFactory.checkAcceptCredPermission(myName, myName); + } InitSecContextToken token = new InitSecContextToken(this, - secretKeys, is); + (Krb5AcceptCredential) myCred, is); PrincipalName clientName = token.getKrbApReq().getClient(); peerName = Krb5NameElement.getInstance(clientName); + + // If unbound, check after the bound name is found + if (myName == null) { + myName = Krb5NameElement.getInstance( + token.getKrbApReq().getCreds().getServer()); + Krb5MechFactory.checkAcceptCredPermission(myName, myName); + } + if (getMutualAuthState()) { retVal = new AcceptSecContextToken(this, token.getKrbApReq()).encode(); diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java b/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java index d9552a1ec6aa4158707ea8b5dc56df2e083d4976..a1995293314384cb987cbd3f3033a41e8e1920a4 100644 --- a/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java +++ b/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java @@ -158,7 +158,7 @@ public final class Krb5MechFactory implements MechanismFactory { public static void checkAcceptCredPermission(Krb5NameElement name, GSSNameSpi originalName) { SecurityManager sm = System.getSecurityManager(); - if (sm != null) { + if (sm != null && name != null) { ServicePermission perm = new ServicePermission (name.getKrb5PrincipalName().getName(), "accept"); try { diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5Util.java b/src/share/classes/sun/security/jgss/krb5/Krb5Util.java index ec5bc9ca43b30a6f0f35e20bec021d8771892b62..f0495eef872d3aa5a9293a53ab84339980f8a77e 100644 --- a/src/share/classes/sun/security/jgss/krb5/Krb5Util.java +++ b/src/share/classes/sun/security/jgss/krb5/Krb5Util.java @@ -186,114 +186,6 @@ public class Krb5Util { return subject; } - /** - * Credentials of a service, the private secret to authenticate its - * identity, which can be: - * 1. Some KerberosKeys (generated from password) - * 2. A KeyTab (for a typical service) - * 3. A TGT (for S4U2proxy extension) - * - * Note that some creds can coexist. For example, a user2user service - * can use its keytab (or keys) if the client can successfully obtain a - * normal service ticket, otherwise, it can uses the TGT (actually, the - * session key of the TGT) if the client can only acquire a service ticket - * of ENC-TKT-IN-SKEY style. - */ - public static class ServiceCreds { - private KerberosPrincipal kp; - private List ktabs; - private List kk; - private Subject subj; - private KerberosTicket tgt; - - private static ServiceCreds getInstance( - Subject subj, String serverPrincipal) { - - ServiceCreds sc = new ServiceCreds(); - sc.subj = subj; - - for (KerberosPrincipal p: subj.getPrincipals(KerberosPrincipal.class)) { - if (serverPrincipal == null || - p.getName().equals(serverPrincipal)) { - sc.kp = p; - serverPrincipal = p.getName(); - break; - } - } - if (sc.kp == null) { - // Compatibility with old behavior: even when there is no - // KerberosPrincipal, we can find one from KerberosKeys - List keys = SubjectComber.findMany( - subj, serverPrincipal, null, KerberosKey.class); - if (!keys.isEmpty()) { - sc.kp = keys.get(0).getPrincipal(); - serverPrincipal = sc.kp.getName(); - if (DEBUG) { - System.out.println(">>> ServiceCreds: no kp?" - + " find one from kk: " + serverPrincipal); - } - } else { - return null; - } - } - sc.ktabs = SubjectComber.findMany( - subj, null, null, KeyTab.class); - sc.kk = SubjectComber.findMany( - subj, serverPrincipal, null, KerberosKey.class); - sc.tgt = SubjectComber.find( - subj, null, serverPrincipal, KerberosTicket.class); - if (sc.ktabs.isEmpty() && sc.kk.isEmpty() && sc.tgt == null) { - return null; - } - return sc; - } - - public String getName() { - return kp.getName(); - } - - public KerberosKey[] getKKeys() { - List keys = new ArrayList<>(); - for (KerberosKey k: kk) { - keys.add(k); - } - for (KeyTab ktab: ktabs) { - for (KerberosKey k: ktab.getKeys(kp)) { - keys.add(k); - } - } - return keys.toArray(new KerberosKey[keys.size()]); - } - - public EncryptionKey[] getEKeys() { - KerberosKey[] kkeys = getKKeys(); - EncryptionKey[] ekeys = new EncryptionKey[kkeys.length]; - for (int i=0; i allPrincs; + + // All private credentials that can be used + private List ktabs; + private List kk; + private KerberosTicket tgt; + + private boolean destroyed; + + private ServiceCreds() { + // Make sure this class cannot be instantiated externally. + } + + /** + * Creates a ServiceCreds object based on info in a Subject for + * a given principal name (if specified). + * @return the object, or null if there is no private creds for it + */ + public static ServiceCreds getInstance( + Subject subj, String serverPrincipal) { + + ServiceCreds sc = new ServiceCreds(); + + sc.allPrincs = + subj.getPrincipals(KerberosPrincipal.class); + + // Compatibility. A key implies its own principal + for (KerberosKey key: SubjectComber.findMany( + subj, serverPrincipal, null, KerberosKey.class)) { + sc.allPrincs.add(key.getPrincipal()); + } + + if (serverPrincipal != null) { // A named principal + sc.kp = new KerberosPrincipal(serverPrincipal); + } else { + if (sc.allPrincs.size() == 1) { // choose the only one + sc.kp = sc.allPrincs.iterator().next(); + serverPrincipal = sc.kp.getName(); + } + } + + sc.ktabs = SubjectComber.findMany( + subj, serverPrincipal, null, KeyTab.class); + sc.kk = SubjectComber.findMany( + subj, serverPrincipal, null, KerberosKey.class); + sc.tgt = SubjectComber.find( + subj, null, serverPrincipal, KerberosTicket.class); + if (sc.ktabs.isEmpty() && sc.kk.isEmpty() && sc.tgt == null) { + return null; + } + + sc.destroyed = false; + + return sc; + } + + // can be null + public String getName() { + if (destroyed) { + throw new IllegalStateException("This object is destroyed"); + } + return kp == null ? null : kp.getName(); + } + + /** + * Gets keys for someone unknown. + * Used by TLS or as a fallback in getEKeys(). Can still return an + * empty array. + */ + public KerberosKey[] getKKeys() { + if (destroyed) { + throw new IllegalStateException("This object is destroyed"); + } + if (kp != null) { + return getKKeys(kp); + } else if (!allPrincs.isEmpty()) { + return getKKeys(allPrincs.iterator().next()); + } + return new KerberosKey[0]; + } + + /** + * Get kkeys for a principal, + * @param princ the target name initiator requests. Not null. + * @return keys for the princ, never null, might be empty + */ + private KerberosKey[] getKKeys(KerberosPrincipal princ) { + ArrayList keys = new ArrayList<>(); + if (kp != null && !princ.equals(kp)) { + return new KerberosKey[0]; // Not me + } + if (!allPrincs.contains(princ)) { + return new KerberosKey[0]; // Not someone I know, This check + // is necessary but a KeyTab has + // no principal name recorded. + } + for (KerberosKey k: kk) { + if (k.getPrincipal().equals(princ)) { + keys.add(k); + } + } + for (KeyTab ktab: ktabs) { + for (KerberosKey k: ktab.getKeys(princ)) { + keys.add(k); + } + } + return keys.toArray(new KerberosKey[keys.size()]); + } + + /** + * Gets EKeys for a principal. + * @param princ the target name initiator requests. Not null. + * @return keys for the princ, never null, might be empty + */ + public EncryptionKey[] getEKeys(PrincipalName princ) { + if (destroyed) { + throw new IllegalStateException("This object is destroyed"); + } + KerberosKey[] kkeys = getKKeys(new KerberosPrincipal(princ.getName())); + if (kkeys.length == 0) { + // Note: old JDK does not perform real name checking. If the + // acceptor starts by name A but initiator requests for B, + // as long as their keys match (i.e. A's keys can decrypt B's + // service ticket), the authentication is OK. There are real + // customers depending on this to use different names for a + // single service. + kkeys = getKKeys(); + } + EncryptionKey[] ekeys = new EncryptionKey[kkeys.length]; + for (int i=0; i answer = (oneOnly ? null : new ArrayList ()); - if (credClass == KeyTab.class) { // Principal un-related - // We are looking for credentials unrelated to serverPrincipal - Iterator iterator = - subject.getPrivateCredentials(credClass).iterator(); - while (iterator.hasNext()) { - T t = iterator.next(); - if (DEBUG) { - System.out.println("Found " + credClass.getSimpleName()); + if (credClass == KeyTab.class) { + // TODO: There is currently no good way to filter out keytabs + // not for serverPrincipal. We can only check the principal + // set. If the server is not there, we can be sure none of the + // keytabs should be used, otherwise, use all for safety. + boolean useAll = false; + if (serverPrincipal != null) { + for (KerberosPrincipal princ: + subject.getPrincipals(KerberosPrincipal.class)) { + if (princ.getName().equals(serverPrincipal)) { + useAll = true; + break; + } } - if (oneOnly) { - return t; - } else { - answer.add(t); + } else { + useAll = true; + } + if (useAll) { + Iterator iterator = + subject.getPrivateCredentials(KeyTab.class).iterator(); + while (iterator.hasNext()) { + KeyTab t = iterator.next(); + if (DEBUG) { + System.out.println("Found " + credClass.getSimpleName() + + " " + t); + } + if (oneOnly) { + return t; + } else { + answer.add(credClass.cast(t)); + } } } } else if (credClass == KerberosKey.class) { @@ -114,11 +133,6 @@ class SubjectComber { if (oneOnly) { return t; } else { - if (serverPrincipal == null) { - // Record name so that keys returned will all - // belong to the same principal - serverPrincipal = name; - } answer.add(credClass.cast(t)); } } diff --git a/src/share/classes/sun/security/krb5/KrbApReq.java b/src/share/classes/sun/security/krb5/KrbApReq.java index f4e52d35f7d810a488de6f25659e4ae29286c3ac..535bb0dc52f525e2a27d13bd62a5c0290640415f 100644 --- a/src/share/classes/sun/security/krb5/KrbApReq.java +++ b/src/share/classes/sun/security/krb5/KrbApReq.java @@ -34,6 +34,7 @@ package sun.security.krb5; import sun.security.krb5.internal.*; import sun.security.krb5.internal.crypto.*; import sun.security.krb5.internal.rcache.*; +import sun.security.jgss.krb5.Krb5AcceptCredential; import java.net.InetAddress; import sun.security.util.*; import java.io.IOException; @@ -135,13 +136,13 @@ public class KrbApReq { */ // Used in InitSecContextToken (for AP_REQ and not TGS REQ) public KrbApReq(byte[] message, - EncryptionKey[] keys, + Krb5AcceptCredential cred, InetAddress initiator) throws KrbException, IOException { obuf = message; if (apReqMessg == null) decode(); - authenticate(keys, initiator); + authenticate(cred, initiator); } /** @@ -260,10 +261,11 @@ public class KrbApReq { } } - private void authenticate(EncryptionKey[] keys, InetAddress initiator) + private void authenticate(Krb5AcceptCredential cred, InetAddress initiator) throws KrbException, IOException { int encPartKeyType = apReqMessg.ticket.encPart.getEType(); Integer kvno = apReqMessg.ticket.encPart.getKeyVersionNumber(); + EncryptionKey[] keys = cred.getKrb5EncryptionKeys(apReqMessg.ticket.sname); EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, kvno, keys); if (dkey == null) { diff --git a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java index b2a71ce6693024463d98101f975c187bfc63fdf2..d1023de9de3f3b44b9ae61b705f46ecbfa4d758e 100644 --- a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java +++ b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java @@ -382,9 +382,15 @@ public class KeyTab implements KeyTabConstants { */ public void addEntry(PrincipalName service, char[] psswd, int kvno, boolean append) throws KrbException { + addEntry(service, service.getSalt(), psswd, kvno, append); + } + + // Called by KDC test + public void addEntry(PrincipalName service, String salt, char[] psswd, + int kvno, boolean append) throws KrbException { EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys( - psswd, service.getSalt()); + psswd, salt); // There should be only one maximum KVNO value for all etypes, so that // all added keys can have the same KVNO. diff --git a/src/share/classes/sun/security/provider/PolicyFile.java b/src/share/classes/sun/security/provider/PolicyFile.java index 74e18c36ea8b5e893b0227fbc870d7eee6cbd243..5ea389b51e9dbc30b3ea550462f2080b1dfb3e21 100644 --- a/src/share/classes/sun/security/provider/PolicyFile.java +++ b/src/share/classes/sun/security/provider/PolicyFile.java @@ -31,13 +31,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URI; import java.util.*; -import java.util.Enumeration; -import java.util.List; -import java.util.StringTokenizer; -import java.util.ArrayList; -import java.util.ListIterator; import java.text.MessageFormat; -import com.sun.security.auth.PrincipalComparator; import java.security.*; import java.security.cert.Certificate; import java.security.cert.X509Certificate; @@ -46,19 +40,7 @@ import javax.security.auth.x500.X500Principal; import java.io.FilePermission; import java.net.SocketPermission; import java.net.NetPermission; -import java.util.PropertyPermission; import java.util.concurrent.atomic.AtomicReference; -/* -import javax.security.auth.AuthPermission; -import javax.security.auth.kerberos.ServicePermission; -import javax.security.auth.kerberos.DelegationPermission; -import java.io.SerializablePermission; -import java.util.logging.LoggingPermission; -import java.sql.SQLPermission; -import java.lang.reflect.ReflectPermission; -import javax.sound.sampled.AudioPermission; -import javax.net.ssl.SSLPermission; -*/ import sun.misc.JavaSecurityProtectionDomainAccess; import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; import sun.misc.SharedSecrets; @@ -794,12 +776,9 @@ public class PolicyFile extends java.security.Policy { debug.println("Adding policy entry: "); debug.println(" signedBy " + ge.signedBy); debug.println(" codeBase " + ge.codeBase); - if (ge.principals != null && ge.principals.size() > 0) { - ListIterator li = - ge.principals.listIterator(); - while (li.hasNext()) { - PolicyParser.PrincipalEntry pppe = li.next(); - debug.println(" " + pppe.toString()); + if (ge.principals != null) { + for (PolicyParser.PrincipalEntry pppe : ge.principals) { + debug.println(" " + pppe.toString()); } } } @@ -955,11 +934,15 @@ public class PolicyFile extends java.security.Policy { InvocationTargetException { //XXX we might want to keep a hash of created factories... - Class> pc = Class.forName(type); + Class> pc = Class.forName(type, false, null); Permission answer = getKnownInstance(pc, name, actions); if (answer != null) { return answer; } + if (!Permission.class.isAssignableFrom(pc)) { + // not the right subtype + throw new ClassCastException(type + " is not a Permission"); + } if (name == null && actions == null) { try { @@ -1001,7 +984,6 @@ public class PolicyFile extends java.security.Policy { */ private static final Permission getKnownInstance(Class> claz, String name, String actions) { - // XXX shorten list to most popular ones? if (claz.equals(FilePermission.class)) { return new FilePermission(name, actions); } else if (claz.equals(SocketPermission.class)) { @@ -1014,30 +996,6 @@ public class PolicyFile extends java.security.Policy { return new NetPermission(name, actions); } else if (claz.equals(AllPermission.class)) { return SecurityConstants.ALL_PERMISSION; -/* - } else if (claz.equals(ReflectPermission.class)) { - return new ReflectPermission(name, actions); - } else if (claz.equals(SecurityPermission.class)) { - return new SecurityPermission(name, actions); - } else if (claz.equals(PrivateCredentialPermission.class)) { - return new PrivateCredentialPermission(name, actions); - } else if (claz.equals(AuthPermission.class)) { - return new AuthPermission(name, actions); - } else if (claz.equals(ServicePermission.class)) { - return new ServicePermission(name, actions); - } else if (claz.equals(DelegationPermission.class)) { - return new DelegationPermission(name, actions); - } else if (claz.equals(SerializablePermission.class)) { - return new SerializablePermission(name, actions); - } else if (claz.equals(AudioPermission.class)) { - return new AudioPermission(name, actions); - } else if (claz.equals(SSLPermission.class)) { - return new SSLPermission(name, actions); - } else if (claz.equals(LoggingPermission.class)) { - return new LoggingPermission(name, actions); - } else if (claz.equals(SQLPermission.class)) { - return new SQLPermission(name, actions); -*/ } else { return null; } @@ -1079,7 +1037,7 @@ public class PolicyFile extends java.security.Policy { if (cert != null) { if (vcerts == null) - vcerts = new ArrayList (); + vcerts = new ArrayList<>(); vcerts.add(cert); } } @@ -1329,7 +1287,7 @@ public class PolicyFile extends java.security.Policy { List entryPs = entry.getPrincipals(); if (debug != null) { - ArrayList accPs = new ArrayList<>(); + List accPs = new ArrayList<>(); if (principals != null) { for (int i = 0; i < principals.length; i++) { accPs.add(new PolicyParser.PrincipalEntry @@ -1368,79 +1326,72 @@ public class PolicyFile extends java.security.Policy { // has principals. see if policy entry principals match // principals in current ACC - for (int i = 0; i < entryPs.size(); i++) { - PolicyParser.PrincipalEntry pppe = entryPs.get(i); - - // see if principal entry is a PrincipalComparator - - try { - Class> pClass = Class.forName - (pppe.principalClass, - true, - Thread.currentThread().getContextClassLoader()); - - if (!PrincipalComparator.class.isAssignableFrom(pClass)) { - - // common case - dealing with regular Principal class. - // see if policy entry principal is in current ACC + for (PolicyParser.PrincipalEntry pppe : entryPs) { - if (!checkEntryPs(principals, pppe)) { - if (debug != null) { - debug.println("evaluation (principals) failed"); - } + // Check for wildcards + if (pppe.isWildcardClass()) { + // a wildcard class matches all principals in current ACC + continue; + } - // policy entry principal not in current ACC - - // immediately return and go to next policy entry - return; + if (pppe.isWildcardName()) { + // a wildcard name matches any principal with the same class + for (Principal p : principals) { + if (pppe.principalClass.equals(p.getClass().getName())) { + continue; } + } + if (debug != null) { + debug.println("evaluation (principal name wildcard) failed"); + } + // policy entry principal not in current ACC - + // immediately return and go to next policy entry + return; + } - } else { + Set pSet = new HashSet<>(Arrays.asList(principals)); + Subject subject = new Subject(true, pSet, + Collections.EMPTY_SET, + Collections.EMPTY_SET); + try { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + Class> pClass = Class.forName(pppe.principalClass, false, cl); + if (!Principal.class.isAssignableFrom(pClass)) { + // not the right subtype + throw new ClassCastException(pppe.principalClass + + " is not a Principal"); + } - // dealing with a PrincipalComparator + Constructor> c = pClass.getConstructor(PARAMS1); + Principal p = (Principal)c.newInstance(new Object[] { + pppe.principalName }); - Constructor> c = pClass.getConstructor(PARAMS1); - PrincipalComparator pc = (PrincipalComparator)c.newInstance - (new Object[] { pppe.principalName }); + if (debug != null) { + debug.println("found Principal " + p.getClass().getName()); + } + // check if the Principal implies the current + // thread's principals + if (!p.implies(subject)) { if (debug != null) { - debug.println("found PrincipalComparator " + - pc.getClass().getName()); + debug.println("evaluation (principal implies) failed"); } - // check if the PrincipalComparator - // implies the current thread's principals - - Set pSet = new HashSet<>(principals.length); - for (int j = 0; j < principals.length; j++) { - pSet.add(principals[j]); - } - Subject subject = new Subject(true, - pSet, - Collections.EMPTY_SET, - Collections.EMPTY_SET); - - if (!pc.implies(subject)) { - if (debug != null) { - debug.println - ("evaluation (principal comparator) failed"); - } - - // policy principal does not imply the current Subject - - // immediately return and go to next policy entry - return; - } + // policy principal does not imply the current Subject - + // immediately return and go to next policy entry + return; } } catch (Exception e) { - // fall back to regular principal comparison. + // fall back to default principal comparison. // see if policy entry principal is in current ACC if (debug != null) { e.printStackTrace(); } - if (!checkEntryPs(principals, pppe)) { + if (!pppe.implies(subject)) { if (debug != null) { - debug.println("evaluation (principals) failed"); + debug.println("evaluation (default principal implies) failed"); } // policy entry principal not in current ACC - @@ -1450,7 +1401,7 @@ public class PolicyFile extends java.security.Policy { } // either the principal information matched, - // or the PrincipalComparator.implies succeeded. + // or the Principal.implies succeeded. // continue loop and test the next policy principal } @@ -1484,47 +1435,6 @@ public class PolicyFile extends java.security.Policy { } } - /** - * This method returns, true, if the principal in the policy entry, - * pppe, is part of the current thread's principal array, pList. - * This method also returns, true, if the policy entry's principal - * is appropriately wildcarded. - * - * Note that the provided pppe argument may have - * wildcards (*) for both the Principal
class and name. - * - * @param pList an array of principals from the current thread's - * AccessControlContext. - * - * @param pppe a Principal specified in a policy grant entry. - * - * @return true if the current thread's pList "contains" the - * principal in the policy entry, pppe. This method - * also returns true if the policy entry's principal - * appropriately wildcarded. - */ - private boolean checkEntryPs(Principal[] pList, - PolicyParser.PrincipalEntry pppe) { - - for (int i = 0; i < pList.length; i++) { - - if (pppe.principalClass.equals - (PolicyParser.PrincipalEntry.WILDCARD_CLASS) || - pppe.principalClass.equals - (pList[i].getClass().getName())) { - - if (pppe.principalName.equals - (PolicyParser.PrincipalEntry.WILDCARD_NAME) || - pppe.principalName.equals - (pList[i].getName())) { - - return true; - } - } - } - return false; - } - /** ** @@ -1568,8 +1478,7 @@ public class PolicyFile extends java.security.Policy { sb.append(sp.getSelfName().substring(startIndex, v)); // expand SELF - ListIterator
pli = - entryPs.listIterator(); + Iterator pli = entryPs.iterator(); while (pli.hasNext()) { PolicyParser.PrincipalEntry pppe = pli.next(); String[][] principalInfo = getPrincipalInfo(pppe,pdp); @@ -1596,8 +1505,8 @@ public class PolicyFile extends java.security.Policy { try { // first try to instantiate the permission perms.add(getInstance(sp.getSelfType(), - sb.toString(), - sp.getSelfActions())); + sb.toString(), + sp.getSelfActions())); } catch (ClassNotFoundException cnfe) { // ok, the permission is not in the bootclasspath. // before we add an UnresolvedPermission, check to see @@ -1673,10 +1582,7 @@ public class PolicyFile extends java.security.Policy { // 2) the entry's Principal name is wildcarded only // 3) the entry's Principal class and name are wildcarded - if (!pe.principalClass.equals - (PolicyParser.PrincipalEntry.WILDCARD_CLASS) && - !pe.principalName.equals - (PolicyParser.PrincipalEntry.WILDCARD_NAME)) { + if (!pe.isWildcardClass() && !pe.isWildcardName()) { // build an info array for the principal // from the Policy entry @@ -1685,24 +1591,19 @@ public class PolicyFile extends java.security.Policy { info[0][1] = pe.principalName; return info; - } else if (!pe.principalClass.equals - (PolicyParser.PrincipalEntry.WILDCARD_CLASS) && - pe.principalName.equals - (PolicyParser.PrincipalEntry.WILDCARD_NAME)) { + } else if (!pe.isWildcardClass() && pe.isWildcardName()) { // build an info array for every principal // in the current domain which has a principal class // that is equal to policy entry principal class name List plist = new ArrayList<>(); for (int i = 0; i < pdp.length; i++) { - if(pe.principalClass.equals(pdp[i].getClass().getName())) + if (pe.principalClass.equals(pdp[i].getClass().getName())) plist.add(pdp[i]); } String[][] info = new String[plist.size()][2]; int i = 0; - java.util.Iterator pIterator = plist.iterator(); - while (pIterator.hasNext()) { - Principal p = pIterator.next(); + for (Principal p : plist) { info[i][0] = p.getClass().getName(); info[i][1] = p.getName(); i++; @@ -1763,7 +1664,7 @@ public class PolicyFile extends java.security.Policy { // Done return certs; - ArrayList userCertList = new ArrayList<>(); + List userCertList = new ArrayList<>(); i = 0; while (i < certs.length) { userCertList.add(certs[i]); @@ -1889,10 +1790,8 @@ public class PolicyFile extends java.security.Policy { if (principals == null || principals.isEmpty() || keystore == null) return true; - ListIterator i = principals.listIterator(); - while (i.hasNext()) { - PolicyParser.PrincipalEntry pppe = i.next(); - if (pppe.principalClass.equals(PolicyParser.REPLACE_NAME)) { + for (PolicyParser.PrincipalEntry pppe : principals) { + if (pppe.isReplaceName()) { // perform replacement // (only X509 replacement is possible now) @@ -2241,8 +2140,7 @@ public class PolicyFile extends java.security.Policy { if (this.certs == null) { // extract the signer certs - ArrayList signerCerts = - new ArrayList<>(); + List signerCerts = new ArrayList<>(); i = 0; while (i < certs.length) { signerCerts.add(certs[i]); @@ -2406,11 +2304,10 @@ public class PolicyFile extends java.security.Policy { private java.util.Random random; PolicyInfo(int numCaches) { - policyEntries = new ArrayList (); + policyEntries = new ArrayList<>(); identityPolicyEntries = Collections.synchronizedList(new ArrayList (2)); - aliasMapping = Collections.synchronizedMap( - new HashMap