undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,58 @@
#
# Copyright (c) 2024, 2026, 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.
#
# 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.
#
#############################################################################
#
# List of quarantined tests for testing in AOT_JDK mode.
#
#############################################################################
java/math/BigInteger/largeMemory/DivisionOverflow.java 0000000 generic-all
java/math/BigInteger/largeMemory/StringConstructorOverflow.java 0000000 generic-all
jdk/internal/misc/CDS/ArchivedEnumTest.java 0000000 generic-all
java/lang/module/ModuleDescriptorHashCodeTest.java 0000000 generic-all
# The test case is incorrect. There's no guarantee that running a JVM with the following
# parameters will always cause the class java/lang/invoke/MethodHandleStatics to be initialized
java/lang/invoke/DumpMethodHandleInternals.java 0000000 generic-all
# This test checks for a warning message that's already printed by
# sun.util.locale.BaseLocale.<clinit> during the training run. Because BaseLocale is aot-initialized,
# this message will not be printed in the production run.
java/util/Locale/UseOldISOCodesTest.java 0000000 generic-all
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

View file

@ -0,0 +1,39 @@
###########################################################################
#
# Copyright (c) 2025, 2026, 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.
#
# 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.
#
###########################################################################
# Currently empty
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

View file

@ -0,0 +1,48 @@
#
# Copyright (c) 2022, 2026, 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.
#
# 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.
#
com/sun/jdi/EATests.java#id0 8264699 generic-all
##########
## Tests failing when main() is executed in additional vthread or in vthread instead of thread
#
com/sun/jdi/ExceptionEvents.java 8278470 generic-all
com/sun/jdi/RedefineCrossStart.java 8278470 generic-all
java/lang/ScopedValue/StressStackOverflow.java#default 8309646 generic-all
java/lang/ScopedValue/StressStackOverflow.java#no-TieredCompilation 8309646 generic-all
java/lang/ScopedValue/StressStackOverflow.java#TieredStopAtLevel1 8309646 generic-all
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

View file

@ -0,0 +1,44 @@
#
# Copyright (c) 2018, 2026, 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.
#
# 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.
#
#############################################################################
#
# List of quarantined tests for testing in Xcomp mode.
#
#############################################################################
java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all
java/lang/reflect/callerCache/ReflectionCallerCacheTest.java 8332028 generic-all
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

View file

@ -0,0 +1,41 @@
#
# Copyright (c) 2026, 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.
#
# 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.
#
#############################################################################
#
# List of quarantined tests for testing with -XX:+UseCompactObjectHeaders
#
#############################################################################
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

View file

@ -0,0 +1,32 @@
#
# Copyright (c) 2025, 2026, 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.
#
# 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.
#
#############################################################################
#
# List of quarantined tests for testing with --enable-preview
#
# These are failures that ONLY occur with the '--enable-preview' option
# specified. There are separate sub-sections for each preview project.
#
#############################################################################

View file

@ -0,0 +1,44 @@
#
# Copyright (c) 2025, 2026, 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.
#
# 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.
#
# List of tests incompatible with jvmti stress agent or requiring more investigation
com/sun/jdi/EATests.java#id0 0000000 generic-all
com/sun/jdi/ThreadMemoryLeakTest.java 0000000 generic-all
# weak referenced are not cleared
java/lang/WeakPairMap/Driver.java 0000000 generic-all
java/lang/ref/ReachabilityFenceTest.java 0000000 generic-all
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

View file

@ -0,0 +1,72 @@
#
# Copyright Amazon.com Inc. 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.
#
# 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.
#
#############################################################################
#
# List of quarantined tests for testing with Shenandoah.
#
#############################################################################
# Quiet all LeakProfiler tests
jdk/jfr/api/consumer/TestRecordingFileWrite.java 8342951 generic-all
jdk/jfr/event/oldobject/TestAllocationTime.java 8342951 generic-all
jdk/jfr/event/oldobject/TestArrayInformation.java 8342951 generic-all
jdk/jfr/event/oldobject/TestCircularReference.java 8342951 generic-all
jdk/jfr/event/oldobject/TestClassLoaderLeak.java 8342951 generic-all
jdk/jfr/event/oldobject/TestFieldInformation.java 8342951 generic-all
jdk/jfr/event/oldobject/TestG1.java 8342951 generic-all
jdk/jfr/event/oldobject/TestHeapDeep.java 8342951 generic-all
jdk/jfr/event/oldobject/TestHeapShallow.java 8342951 generic-all
jdk/jfr/event/oldobject/TestLargeRootSet.java 8342951 generic-all
jdk/jfr/event/oldobject/TestLastKnownHeapUsage.java 8342951 generic-all
jdk/jfr/event/oldobject/TestListenerLeak.java 8342951 generic-all
jdk/jfr/event/oldobject/TestMetadataRetention.java 8342951 generic-all
jdk/jfr/event/oldobject/TestObjectAge.java 8342951 generic-all
jdk/jfr/event/oldobject/TestObjectDescription.java 8342951 generic-all
jdk/jfr/event/oldobject/TestObjectSize.java 8342951 generic-all
jdk/jfr/event/oldobject/TestParallel.java 8342951 generic-all
jdk/jfr/event/oldobject/TestReferenceChainLimit.java 8342951 generic-all
jdk/jfr/event/oldobject/TestSanityDefault.java 8342951 generic-all
jdk/jfr/event/oldobject/TestSerial.java 8342951 generic-all
jdk/jfr/event/oldobject/TestShenandoah.java 8342951 generic-all
jdk/jfr/event/oldobject/TestThreadLocalLeak.java 8342951 generic-all
jdk/jfr/event/oldobject/TestZ.java 8342951 generic-all
jdk/jfr/jcmd/TestJcmdDump.java 8342951 generic-all
jdk/jfr/jcmd/TestJcmdDumpPathToGCRoots.java 8342951 generic-all
jdk/jfr/jcmd/TestJcmdStartPathToGCRoots.java 8342951 generic-all
jdk/jfr/jvm/TestWaste.java 8342951 generic-all
jdk/jfr/startupargs/TestOldObjectQueueSize.java 8342951 generic-all
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

View file

@ -0,0 +1,43 @@
#
# Copyright (c) 2020, 2026, 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.
#
# 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.
#
#############################################################################
#
# List of quarantined tests for testing with ZGC.
#
#############################################################################
com/sun/jdi/ThreadMemoryLeakTest.java 8307402 generic-all
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

795
test/jdk/ProblemList.txt Normal file
View file

@ -0,0 +1,795 @@
###########################################################################
#
# Copyright (c) 2009, 2026, 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.
#
# 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.
#
###########################################################################
#
# List of tests that should not be run by test/Makefile, for various reasons:
# 1. Does not run with jtreg -samevm mode
# 2. Causes problems in jtreg -samevm mode for jtreg or tests that follow it
# 3. The test is too slow or consumes too many system resources
# 4. The test fails when run on any official build systems
#
# It is possible that a test being on this list is a mistake, and that some
# other test in samevm mode caused tests to fail, mistakes happen.
#
# Tests marked @ignore are not run by test/Makefile, but harmless to be listed.
#
# Tests that explicitly state "@run main/othervm ...", and are not listed here,
# will be run in the same batch as the samevm tests.
#
# Shell tests are othervm by default.
#
# List items are testnames followed by labels, all MUST BE commented
# as to why they are here and use a label:
# generic-all Problems on all platforms
# generic-ARCH Where ARCH is one of: x64, i586, ppc64, ppc64le, s390x, aarch64 etc.
# OSNAME-all Where OSNAME is one of: linux, windows, macosx, aix
# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. macosx-x64
# OSNAME-REV Specific on to one OSNAME and REV, e.g. macosx-10.7.4
#
# More than one label is allowed but must be on the same line comma seperated,
# without spaces.
# If there are several lines mentioning the same test, the last one is used.
#
#############################################################################
#
# Running the tests:
# cd test && make JT_HOME=jtreg_home PRODUCT_HOME=jdk_home jdk_all
# Or instead of jdk_all, use any of the jdk_* targets.
#
# Samevm Notes:
# * Although some tests may have only been seen to fail on some platforms,
# they might be flagged as 'generic-all' because the problem they have
# could cause hidden slowdowns on other platforms.
# Most samevm problems will be generic-all, but windows usually dislikes
# them the most.
# Address already in use or connection errors indicate a generic port issue.
# (this is not necessarily a samevm issue, but an issue for running the tests
# on shared machines, two people or two test runs will collide).
# * Samevm problem (windows in particular) is not closing all input/output
# * Samevm problem when a test calls setSecurityManager()
# * Samevm problem with setHttps*() is used? (not exactly sure here)
# * Samevm problem when stuffing system properties with non Strings or anything
# * Samevm problem when changing vm settings, or registering any vm actions
# * Samevm problems with deleteOnExit(), if it must happen at end of test
# * Samevm problems with URLClassLoader? (no details here)
# * Samevm problems with dependence on predictable GC or finalizations
#
# Any of the above problems may mean the test needs to be flagged as "othervm".
#
#############################################################################
#
# Fixing the tests:
#
# Some tests just may need to be run with "othervm", and that can easily be
# done by adding a @run line (or modifying any existing @run):
# @run main/othervm NameOfMainClass
# Make sure this @run follows any use of @library.
# Otherwise, if the test is a samevm possibility, make sure the test is
# cleaning up after itself, closing all streams, deleting temp files, etc.
#
# Keep in mind that the bug could be in many places, and even different per
# platform, it could be a bug in any one of:
# - the testcase
# - the jdk (jdk classes, native code, or hotspot)
# - the native compiler
# - the javac compiler
# - the OS (depends on what the testcase does)
#
# If you managed to really fix one of these tests, here is how you can
# remove tests from this list:
# 1. Make sure test passes on all platforms with samevm, or mark it othervm
# 2. Make sure test passes on all platforms when run with it's entire group
# 3. Make sure both VMs are tested, -server and -client, if possible
# 4. Use your favorite build and test system to verify these results
# 5. Delete lines in this file, include the changes with your test changes
#
# You may need to repeat your testing 2 or even 3 times to verify good
# results, some of these samevm failures are not very predictable.
#
#############################################################################
############################################################################
# jdk_awt
java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.java 8168389 windows-all,macosx-all
java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java 8224055 macosx-all
java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generic-all
java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all
java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java 6848406 generic-all
java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java 6848407 generic-all
java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java 8340374 macosx-all
java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all
java/awt/Frame/RestoreToOppositeScreen/RestoreToOppositeScreen.java 8286840 linux-all
java/awt/Frame/InitialIconifiedTest.java 7144049,8203920 macosx-all,linux-all
java/awt/Frame/FocusTest.java 8341480 macosx-all
java/awt/FileDialog/FileDialogIconTest/FileDialogIconTest.java 8160558 windows-all
java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion.java 8060176 windows-all,macosx-all
java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_1.java 8060176 windows-all,macosx-all
java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.java 8353673 macosx-all
java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java 8171510 macosx-all
java/awt/dnd/MissingDragExitEventTest/MissingDragExitEventTest.java 8288839 windows-x64,macosx-all
java/awt/dnd/DragExitBeforeDropTest.java 8242805 macosx-all
java/awt/dnd/DragThresholdTest.java 8076299 macosx-all
java/awt/dnd/CustomDragCursorTest.java 8242805 macosx-all
java/awt/Focus/ChoiceFocus/ChoiceFocus.java 8169103 windows-all,macosx-all
java/awt/Focus/ClearLwQueueBreakTest/ClearLwQueueBreakTest.java 8198618 macosx-all
java/awt/Focus/ConsumeNextKeyTypedOnModalShowTest/ConsumeNextKeyTypedOnModalShowTest.java 6986252 macosx-all
java/awt/Focus/MouseClickRequestFocusRaceTest/MouseClickRequestFocusRaceTest.java 8194753 linux-all,macosx-all
java/awt/Focus/NoAutotransferToDisabledCompTest/NoAutotransferToDisabledCompTest.java 7152980 macosx-all
java/awt/Focus/ToFrontFocusTest/ToFrontFocus.java 7156130 linux-all
java/awt/Focus/WrongKeyTypedConsumedTest/WrongKeyTypedConsumedTest.java 8169096 macosx-all
java/awt/Focus/TestDisabledAutoTransfer.java 8159871 macosx-all,windows-all
java/awt/Focus/TestDisabledAutoTransferSwing.java 6962362 windows-all
java/awt/Focus/ActivateOnProperAppContextTest.java 8136516 macosx-all
java/awt/Focus/FocusPolicyTest.java 7160904 linux-all
java/awt/Graphics/SmallPrimitives.java 8047070 macosx-all,linux-all
java/awt/EventQueue/6980209/bug6980209.java 8198615 macosx-all
java/awt/EventQueue/PushPopDeadlock/PushPopDeadlock.java 8024034 generic-all
java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150 macosx-all
java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all
java/awt/List/KeyEventsTest/KeyEventsTest.java 8201307 linux-all
java/awt/List/NoEvents/ProgrammaticChange.java 8201307 linux-all
java/awt/Paint/ListRepaint.java 8201307 linux-all
java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java 8370584 windows-x64
java/awt/Mixing/AWT_Mixing/OpaqueOverlappingChoice.java 8048171 generic-all
java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java 8159451 linux-all,windows-all,macosx-all
java/awt/Mixing/AWT_Mixing/JSplitPaneOverlapping.java 6986109 generic-all
java/awt/Mixing/AWT_Mixing/JInternalFrameMoveOverlapping.java 6986109 windows-all
java/awt/Mixing/AWT_Mixing/MixingPanelsResizing.java 8049405 generic-all
java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java 8049405 macosx-all
java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java 8049405 macosx-all
java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java 8357360 windows-all,linux-all
java/awt/Mixing/NonOpaqueInternalFrame.java 7124549 macosx-all
java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowRetaining.java 6829264 generic-all
java/awt/datatransfer/DragImage/MultiResolutionDragImageTest.java 8080982 generic-all
java/awt/datatransfer/SystemFlavorMap/AddFlavorTest.java 8079268 linux-all
java/awt/datatransfer/ClipboardPerformanceTest.java 8029022 windows-all
java/awt/datatransfer/HTMLTransferConsoleOutputTest.java 8237254 macosx-all
java/awt/datatransfer/ImageTransferCrashTest.java 8237253 macosx-all
java/awt/Toolkit/RealSync/Test.java 6849383 linux-all
java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java 8159252 windows-all
java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java 8072110 macosx-all
java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java 8073636 macosx-all
java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055,8266245 windows-all,linux-all,macosx-all
java/awt/FullScreen/BufferStrategyExceptionTest/BufferStrategyExceptionTest.java 8246558 windows-all
java/awt/Focus/8013611/JDK8013611.java 8175366 windows-all,macosx-all
java/awt/Focus/6981400/Test1.java 8029675 windows-all,macosx-all
java/awt/Focus/6981400/Test3.java 8173264 generic-all
java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java 8169476 windows-all,macosx-all
java/awt/event/KeyEvent/KeyChar/KeyCharTest.java 8169474,8224055 macosx-all,windows-all
java/awt/event/KeyEvent/KeyTyped/CtrlASCII.java 8298910 linux-all
java/awt/dnd/DnDRemoveFocusOwnerCrashTest.java 8242805 macosx-all
java/awt/dnd/DnDCursorCrashTest.java 8242805 macosx-all
java/awt/dnd/DnDClipboardDeadlockTest.java 8079553 linux-all
java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java 8194947 generic-all
java/awt/Frame/FramesGC/FramesGC.java 8079069 macosx-all
java/awt/TrayIcon/ActionCommand/ActionCommand.java 8150540 windows-all
java/awt/TrayIcon/ActionEventMask/ActionEventMask.java 8150540,8295300 windows-all,linux-all
java/awt/TrayIcon/ActionEventTest/ActionEventTest.java 8150540,8242801 windows-all,macosx-all
java/awt/TrayIcon/ModalityTest/ModalityTest.java 8150540,8295300 windows-all,macosx-all,linux-all
java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java 8150540,8295300 windows-all,linux-all
java/awt/TrayIcon/MouseMovedTest/MouseMovedTest.java 8150540,8295300 windows-all,linux-all
java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java 8150540,8295300 windows-all,linux-all
java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java 8150540,8295300 windows-all,linux-all
java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java 8150540,8295300 windows-all,linux-all
java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java 8150540 windows-all
java/awt/TrayIcon/TrayIconPopup/TrayIconPopupClickTest.java 8150540 windows-all,macosx-all
java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java 8150540 windows-all
java/awt/TrayIcon/MouseMoveTest.java 8203053 linux-all
java/awt/TrayIcon/TrayIconKeySelectTest.java 8341557 windows-all
java/awt/TrayIcon/TrayIconTest.java 8341559 generic-all
java/awt/Window/ShapedAndTranslucentWindows/SetShapeAndClick.java 8197936 macosx-all
java/awt/Window/ShapedAndTranslucentWindows/SetShapeDynamicallyAndClick.java 8013450 macosx-all
java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucentWindowClick.java 8013450 macosx-all
java/awt/Window/ShapedAndTranslucentWindows/FocusAWTTest.java 8222328 windows-all,linux-all,macosx-all
java/awt/Window/ShapedAndTranslucentWindows/Shaped.java 8222328 windows-all,linux-all,macosx-all
java/awt/Window/ShapedAndTranslucentWindows/ShapedByAPI.java 8222328 windows-all,linux-all,macosx-all
java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucent.java 8222328 windows-all,linux-all,macosx-all
java/awt/Window/ShapedAndTranslucentWindows/StaticallyShaped.java 8165218,8222328 windows-all,macosx-all,linux-all
java/awt/Window/ShapedAndTranslucentWindows/Translucent.java 8222328 windows-all,linux-all,macosx-all
java/awt/Window/AlwaysOnTop/AutoTestOnTop.java 6847593 linux-all
java/awt/Window/GrabSequence/GrabSequence.java 6848409 macosx-all,linux-all
java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java 8203371 linux-all
java/awt/font/TextLayout/TextLayoutBounds.java 8169188 generic-all
java/awt/image/BufferedImage/ICMColorDataTest/ICMColorDataTest.java 8233028 generic-all
java/awt/image/DrawImage/IncorrectAlphaSurface2SW.java 8056077 linux-all
java/awt/print/Headless/HeadlessPrinterJob.java 8196088 windows-all
sun/awt/datatransfer/SuplementaryCharactersTransferTest.java 8011371 generic-all
sun/awt/shell/ShellFolderMemoryLeak.java 8197794 windows-all
sun/java2d/DirectX/OverriddenInsetsTest/OverriddenInsetsTest.java 8196102 generic-all
sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all
sun/java2d/OpenGL/MultiWindowFillTest.java 8378506 macosx-all
sun/java2d/OpenGL/OpaqueDest.java#id1 8367574 macosx-all
sun/java2d/OpenGL/ScaleParamsOOB.java#id0 8377908 linux-all
sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all
sun/java2d/SunGraphics2D/DrawImageBilinear.java 8297175 linux-all
sun/java2d/SunGraphics2D/PolyVertTest.java 6986565 generic-all
sun/java2d/SunGraphics2D/SimplePrimQuality.java 6992007 generic-all
sun/java2d/SunGraphics2D/SourceClippingBlitTest/SourceClippingBlitTest.java 8196185 generic-all
java/awt/FullScreen/DisplayChangeVITest/DisplayChangeVITest.java 8169469,8273617 windows-all,macosx-aarch64
java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java 8273617 macosx-all
java/awt/print/PrinterJob/PSQuestionMark.java 7003378 generic-all
java/awt/print/PrinterJob/GlyphPositions.java 7003378 generic-all
java/awt/Component/GetScreenLocTest/GetScreenLocTest.java 4753654 generic-all
java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java 8165863 macosx-all
java/awt/Clipboard/PasteNullToTextComponentsTest.java 8234140 macosx-all,windows-all
java/awt/Clipboard/NoOwnerNoTargetsTest.java 8234140 macosx-all
java/awt/Clipboard/LostOwnershipChainTest/SystemClipboard2ProcTest.java 8234140 macosx-all
java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java 8017454 macosx-all
java/awt/Clipboard/ClipboardSecurity.java 8054809 macosx-all
java/awt/Clipboard/GetAltContentsTest/SystemClipboardTest.java 8234140 macosx-all
java/awt/Clipboard/ImageTransferTest.java 8030710 generic-all
java/awt/Clipboard/NoDataConversionFailureTest.java 8234140 macosx-all
java/awt/Dialog/ModalExcludedTest.java 7125054 macosx-all
java/awt/Frame/MiscUndecorated/RepaintTest.java 8266244 macosx-aarch64
java/awt/Modal/FileDialog/FileDialogAppModal1Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogAppModal2Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogAppModal3Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogAppModal4Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogAppModal5Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogAppModal6Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogDocModal1Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogDocModal2Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogDocModal3Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogDocModal4Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogDocModal5Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogDocModal6Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogDocModal7Test.java 7186009 macosx-all,linux-all
java/awt/Modal/FileDialog/FileDialogModal1Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogModal2Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogModal3Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogModal4Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogModal5Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogModal6Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogNonModal1Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogNonModal2Test.java 7186009 macosx-all,linux-all
java/awt/Modal/FileDialog/FileDialogNonModal3Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogNonModal4Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogNonModal5Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogNonModal6Test.java 7186009 macosx-all,linux-all
java/awt/Modal/FileDialog/FileDialogNonModal7Test.java 7186009 macosx-all,linux-all
java/awt/Modal/FileDialog/FileDialogTKModal1Test.java 8196430 generic-all
java/awt/Modal/FileDialog/FileDialogTKModal2Test.java 8196430 generic-all
java/awt/Modal/FileDialog/FileDialogTKModal3Test.java 8196430 generic-all
java/awt/Modal/FileDialog/FileDialogTKModal4Test.java 8196430 generic-all
java/awt/Modal/FileDialog/FileDialogTKModal5Test.java 8196430 generic-all
java/awt/Modal/FileDialog/FileDialogTKModal6Test.java 8196430 generic-all
java/awt/Modal/FileDialog/FileDialogTKModal7Test.java 8196430 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDDAppModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDDDocModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDDModelessTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDDNonModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDDSetModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDDToolkitModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDFAppModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDFSetModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDFToolkitModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDFWModeless1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDFWModeless2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDFWNonModal1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDFWNonModal2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingDocModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDModelessTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDNonModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal3Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWDocModal4Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWModeless1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWModeless2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWModeless3Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWModeless4Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal3Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingFDWNonModal4Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal3Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal4Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal5Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsAppModal6Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsDocModal1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsDocModal2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal3Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal4Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal5Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsSetModal6Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal1Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal2Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal3Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal4Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal5Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/BlockingWindowsToolkitModal6Test.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/UnblockedDialogAppModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/UnblockedDialogDocModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/UnblockedDialogModelessTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/UnblockedDialogNonModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/UnblockedDialogSetModalTest.java 8198665 macosx-all
java/awt/Modal/ModalBlockingTests/UnblockedDialogToolkitModalTest.java 8198665 macosx-all
java/awt/Modal/ModalDialogOrderingTest/ModalDialogOrderingTest.java 8066259 macosx-all
java/awt/Modal/ModalExclusionTests/ApplicationExcludeFrameFileTest.java 8047179 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogFileTest.java 8047179 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogPageSetupTest.java 8196431 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ApplicationExcludeDialogPrintSetupTest.java 8196431 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ApplicationExcludeFramePageSetupTest.java 8196431 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ApplicationExcludeFramePrintSetupTest.java 8196431 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ToolkitExcludeFrameFileTest.java 8047179 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogFileTest.java 8047179 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogPageSetupTest.java 8196431 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ToolkitExcludeDialogPrintSetupTest.java 8196431 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ToolkitExcludeFramePageSetupTest.java 8196431 linux-all,macosx-all
java/awt/Modal/ModalExclusionTests/ToolkitExcludeFramePrintSetupTest.java 8196431 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFAppModal2Test.java 8058813 windows-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFModeless2Test.java 8196191 windows-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFDocModalTest.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFModelessTest.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFNonModalTest.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsModelessTest.java 8196432 linux-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsNonModalTest.java 8196432 linux-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWDocModalTest.java 8196432 linux-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWModelessTest.java 8196432 linux-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFDWNonModalTest.java 8196432 linux-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal1Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal2Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal3Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDAppModal4Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal1Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal2Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal3Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDDocModal4Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless1Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless2Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless3Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDModeless4Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal1Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal2Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal3Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferFWDNonModal4Test.java 8196432 linux-all,macosx-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFDocModal2Test.java 8196432 linux-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal2Test.java 8196432 linux-all
java/awt/Modal/MultipleDialogs/MultipleDialogs1Test.java 8198665 macosx-all
java/awt/Modal/MultipleDialogs/MultipleDialogs2Test.java 8198665 macosx-all
java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665 macosx-all
java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java 8198665 macosx-all
java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java 8198665 macosx-all
java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8177326 macosx-all
java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021 macosx-all
java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java 8051455 macosx-all
java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java 7124407,8302787 macosx-all,windows-all
java/awt/Mouse/RemovedComponentMouseListener/RemovedComponentMouseListener.java 8157170 macosx-all
java/awt/Modal/ToFront/DialogToFrontNonModalTest.java 8221899 linux-all
java/awt/Modal/ToBack/ToBackAppModal1Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackAppModal2Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackAppModal3Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackAppModal4Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackAppModal5Test.java 8196441 macosx-all
java/awt/Modal/ToBack/ToBackAppModal6Test.java 8196441 linux-all
java/awt/Modal/ToBack/ToBackModal1Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackModal2Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackModal3Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackModal4Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackTKModal1Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackTKModal2Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackTKModal3Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackTKModal4Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackTKModal5Test.java 8196441 macosx-all
java/awt/Modal/ToBack/ToBackDocModal1Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackDocModal2Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackDocModal3Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackDocModal4Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackDocModal5Test.java 8196441 linux-all,macosx-all
java/awt/Modal/ToBack/ToBackModeless1Test.java 8196441 macosx-all,linux-all
java/awt/Modal/ToBack/ToBackModeless2Test.java 8196441 macosx-all,linux-all
java/awt/Modal/ToBack/ToBackModeless3Test.java 8196441 macosx-all,linux-all
java/awt/Modal/ToBack/ToBackModeless4Test.java 8196441 macosx-all,linux-all
java/awt/Modal/ToBack/ToBackModeless5Test.java 8196441 macosx-all
java/awt/Modal/ToBack/ToBackNonModal1Test.java 8196441 macosx-all,linux-all
java/awt/Modal/ToBack/ToBackNonModal2Test.java 8196441 macosx-all,linux-all
java/awt/Modal/ToBack/ToBackNonModal3Test.java 8196441 macosx-all,linux-all
java/awt/Modal/ToBack/ToBackNonModal4Test.java 8196441 macosx-all,linux-all
java/awt/Modal/ToBack/ToBackNonModal5Test.java 8196441 macosx-all
javax/print/PrintSEUmlauts/PrintSEUmlauts.java 8135174 generic-all
java/awt/font/Rotate/RotatedTextTest.java 8219641 linux-all
java/awt/font/TextLayout/LigatureCaretTest.java 8266312 generic-all
java/awt/image/VolatileImage/CustomCompositeTest.java 8199002 windows-all,linux-all
java/awt/image/VolatileImage/GradientPaints.java 8199003 linux-all
java/awt/JAWT/JAWT.sh 8197798 windows-all,linux-all
java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java 8202860 linux-all
java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java 8202882 linux-all
java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java 7124275 macosx-all
java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810 macosx-all,linux-all
java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all
java/awt/image/VolatileImage/BitmaskVolatileImage.java 8133102 linux-all
java/awt/ScrollPane/ScrollPaneEventType.java 8296516 macosx-all
java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all
java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all
java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147 linux-all,windows-all,macosx-all
java/awt/Mouse/MouseClickCount.java 8017182 macosx-all
java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java 6847163 linux-all
java/awt/xembed/server/RunTestXEmbed.java 7034201 linux-all
java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java 8164473 linux-all
java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java 7099223,8274106 macosx-all,linux-all,windows-all
java/awt/keyboard/AllKeyCode/AllKeyCode.java 8242930 macosx-all
java/awt/FullScreen/8013581/bug8013581.java 8169471 macosx-all
java/awt/event/MouseEvent/RobotLWTest/RobotLWTest.java 8233568 macosx-all
java/awt/event/MouseEvent/MultipleMouseButtonsTest/MultipleMouseButtonsTest.java 8233568 macosx-all
java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java 8233568 macosx-all
java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java 8233568 macosx-all
java/awt/event/KeyEvent/DeadKey/deadKeyMacOSX.java 8233568 macosx-all
java/awt/TrayIcon/RightClickWhenBalloonDisplayed/RightClickWhenBalloonDisplayed.java 8238720 windows-all
java/awt/PopupMenu/PopupMenuLocation.java 8259913 windows-all
java/awt/GridLayout/ComponentPreferredSize/ComponentPreferredSize.java 8238720,8324782 windows-all,macosx-all
java/awt/GridLayout/ChangeGridSize/ChangeGridSize.java 8238720,8324782 windows-all,macosx-all
java/awt/GridBagLayout/ComponentShortage.java 8355280 windows-all,linux-all
java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsoluteCoordsTest.java 8238720 windows-all
# Several tests which fail sometimes on macos11
java/awt/Window/MainKeyWindowTest/TestMainKeyWindow.java 8265985 macosx-all
java/awt/Robot/Delay/InterruptOfDelay.java 8265986 macosx-all
java/awt/Robot/InfiniteLoopException.java 8342638 windows-all,linux-all
java/awt/MenuBar/TestNoScreenMenuBar.java 8265987 macosx-all
java/awt/Graphics2D/DrawString/DrawRotatedStringUsingRotatedFont.java 8266283 generic-all
java/awt/Graphics2D/DrawString/RotTransText.java 8316878 linux-all
java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.java 8257529 windows-x64
java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.java 8302787 windows-all
java/awt/KeyboardFocusmanager/TypeAhead/MenuItemActivatedTest/MenuItemActivatedTest.java 8302787 windows-all
java/awt/Dialog/MakeWindowAlwaysOnTop/MakeWindowAlwaysOnTop.java 8266243 macosx-aarch64
java/awt/Dialog/ChoiceModalDialogTest.java 8161475 macosx-all
java/awt/Dialog/FileDialogUserFilterTest.java 8001142 generic-all
java/awt/dnd/BadSerializationTest/BadSerializationTest.java 8277817 linux-x64,windows-x64
java/awt/dnd/DragSourceMotionListenerTest.java 8225131 windows-all
java/awt/dnd/RejectDragTest.java 7124259 macosx-all
java/awt/dnd/DnDHTMLToOutlookTest/DnDHTMLToOutlookTest.java 8027424 generic-all
java/awt/GraphicsDevice/DisplayModes/UnknownRefrshRateTest.java 8286436 macosx-aarch64
java/awt/image/multiresolution/MultiresolutionIconTest.java 8291979 linux-x64,windows-all
java/awt/event/SequencedEvent/MultipleContextsFunctionalTest.java 8305061 macosx-x64
sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java 8301177 linux-x64
sun/awt/image/bug8038000.java 8373065 generic-all
# Several tests which fail on some hidpi systems/macosx12-aarch64 system
java/awt/Window/8159168/SetShapeTest.java 8274106 macosx-aarch64
java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 macosx-aarch64
# Wayland related
java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64
sun/java2d/ClassCastExceptionForInvalidSurface.java 8354097 linux-x64
sun/java2d/GdiRendering/ClipShapeRendering.java 8354097 linux-x64
############################################################################
# jdk_beans
java/beans/Introspector/8132566/OverridePropertyInfoTest.java 8132565 generic-all
java/beans/Introspector/8132566/OverrideUserDefPropertyInfoTest.java 8132565 generic-all
java/beans/XMLEncoder/Test6570354.java 8015593 macosx-all
############################################################################
# jdk_lang
java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java 8151492 generic-all
java/lang/invoke/LFCaching/LFGarbageCollectedTest.java 8078602 generic-all
java/lang/invoke/lambda/LambdaFileEncodingSerialization.java 8249079 linux-all
java/lang/invoke/RicochetTest.java 8251969 generic-all
############################################################################
# jdk_instrument
java/lang/instrument/RedefineBigClass.sh 8065756 generic-all
java/lang/instrument/RetransformBigClass.sh 8065756 generic-all
############################################################################
# jdk_io
java/io/pathNames/GeneralWin32.java 8180264 windows-all
java/lang/IO/IO.java 8337935 linux-ppc64le
############################################################################
# jdk_management
java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all
java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java 8247426 generic-all
sun/management/jdp/JdpDefaultsTest.java 8308807,8241865 aix-ppc64,macosx-all
sun/management/jdp/JdpJmxRemoteDynamicPortTest.java 8308807,8241865 aix-ppc64,macosx-all
sun/management/jdp/JdpSpecificAddressTest.java 8308807,8241865 aix-ppc64,macosx-all
sun/management/jdp/JdpOffTest.java 8308807 aix-ppc64
############################################################################
# jdk_jmx
javax/management/remote/mandatory/connection/BrokenConnectionTest.java 8262312 linux-all
############################################################################
# jdk_net
java/net/DatagramSocket/DatagramSocketExample.java 8308807 aix-ppc64
java/net/DatagramSocket/DatagramSocketMulticasting.java 8308807 aix-ppc64
java/net/MulticastSocket/B6427403.java 8308807 aix-ppc64
java/net/MulticastSocket/IPMulticastIF.java 8308807 aix-ppc64
java/net/MulticastSocket/JoinLeave.java 8308807 aix-ppc64
java/net/MulticastSocket/MulticastAddresses.java 8308807 aix-ppc64
java/net/MulticastSocket/NoLoopbackPackets.java 7122846,8308807 macosx-all,aix-ppc64
java/net/MulticastSocket/NoSetNetworkInterface.java 8308807 aix-ppc64
java/net/MulticastSocket/Promiscuous.java 8308807 aix-ppc64
java/net/MulticastSocket/SetGetNetworkInterfaceTest.java 8308807 aix-ppc64
java/net/MulticastSocket/SetLoopbackMode.java 7122846,8308807 macosx-all,aix-ppc64
java/net/MulticastSocket/SetOutgoingIf.java 8308807 aix-ppc64
java/net/MulticastSocket/Test.java 7145658,8308807 macosx-all,aix-ppc64
############################################################################
# jdk_nio
java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8308807,8144003 aix-ppc64,macosx-all
java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64
java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64
java/nio/channels/DatagramChannel/Unref.java 8233437 generic-all
java/nio/channels/DatagramChannel/BasicMulticastTests.java 8144003 macosx-all
java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java 8144003 macosx-all
java/nio/channels/DatagramChannel/Promiscuous.java 8144003 macosx-all
java/nio/channels/SocketChannel/CloseDuringConnect.java 8375658 macosx-26.0,macosx-26.1,macosx-26.2,macosx-26.3
java/nio/channels/SocketChannel/OpenLeak.java 8375658 macosx-26.0,macosx-26.1,macosx-26.2,macosx-26.3
############################################################################
# jdk_rmi
java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java 7140992 generic-all
java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-all
java/rmi/registry/readTest/CodebaseTest.java 8173324 windows-all
java/rmi/registry/multipleRegistries/MultipleRegistries.java 8268182 macosx-all
java/rmi/Naming/DefaultRegistryPort.java 8005619 windows-all
java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java 8005619 windows-all
############################################################################
# jdk_sctp
com/sun/nio/sctp/SctpMultiChannel/SendFailed.java 8141694 linux-all
com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java 8141694 linux-all
com/sun/nio/sctp/SctpChannel/SocketOptionTests.java 8141694 linux-all
############################################################################
# jdk_security
sun/security/smartcardio/TestChannel.java 8039280 generic-all
sun/security/smartcardio/TestConnect.java 8039280 generic-all
sun/security/smartcardio/TestConnectAgain.java 8039280 generic-all
sun/security/smartcardio/TestControl.java 8039280 generic-all
sun/security/smartcardio/TestDefault.java 8039280 generic-all
sun/security/smartcardio/TestDirect.java 8039280 generic-all
sun/security/smartcardio/TestExclusive.java 8039280 generic-all
sun/security/smartcardio/TestMultiplePresent.java 8039280 generic-all
sun/security/smartcardio/TestPresent.java 8039280 generic-all
sun/security/smartcardio/TestTransmit.java 8039280 generic-all
sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8316183 linux-ppc64le
############################################################################
# jdk_sound
javax/sound/sampled/Clip/Drain/ClipDrain.java 7062792 generic-all
############################################################################
# jdk_imageio
############################################################################
# jdk_swing
javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java 8233177 linux-all,windows-all
javax/swing/plaf/basic/BasicDirectoryModel/LoaderThreadCount.java 8333880 windows-all
javax/swing/JFrame/MaximizeWindowTest.java 8321289 linux-all
javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java 8233582 linux-all
javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java 8233582 linux-all
javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java 8194128 macosx-all
javax/swing/JWindow/ShapedAndTranslucentWindows/SetShapeAndClickSwing.java 8013450 macosx-all
javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentJComboBox.java 8024627 macosx-all
# The next test below is an intermittent failure
javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java 8159131 linux-all
javax/swing/JTree/4633594/JTreeFocusTest.java 7105441 macosx-all
javax/swing/AbstractButton/6711682/bug6711682.java 8060765 windows-all,macosx-all
javax/swing/JFileChooser/6396844/TwentyThousandTest.java 8198003 generic-all
javax/swing/JFileChooser/8194044/FileSystemRootTest.java 8327236 windows-all
javax/swing/JPopupMenu/6800513/bug6800513.java 7184956 macosx-all
javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java 8160720 generic-all
javax/swing/JFileChooser/bug6798062.java 8146446 windows-all
javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all
javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765 macosx-all,linux-all
javax/swing/JEditorPane/6917744/bug6917744.java 8213124 macosx-all
# Several tests which fail on some hidpi systems/macosx12-aarch64 system
javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64
javax/swing/JColorChooser/Test6827032.java 8224968 windows-x64
sanity/client/SwingSet/src/ToolTipDemoTest.java 8293001 linux-all
sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java 8265770 macosx-all
sanity/client/SwingSet/src/EditorPaneDemoTest.java 8212240 linux-x64
# This test fails on macOS 14
javax/swing/plaf/synth/7158712/bug7158712.java 8324782 macosx-all
############################################################################
# jdk_text
############################################################################
# jdk_time
############################################################################
# core_tools
############################################################################
# core_svc
############################################################################
# jdk_jdi
com/sun/jdi/InvokeHangTest.java 8218463 linux-all
############################################################################
# jdk_time
############################################################################
# jdk_util
java/util/zip/CloseInflaterDeflaterTest.java 8339216 linux-s390x
############################################################################
# jdk_instrument
############################################################################
# svc_tools
sun/tools/jstatd/TestJstatdRmiPort.java 8251259,8293577 generic-all
############################################################################
# jdk_other
jdk/incubator/vector/ShortMaxVectorTests.java 8306592 generic-i586
jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows-x64
############################################################################
# jdk_jfr
jdk/jfr/event/compiler/TestCodeSweeper.java 8338127 generic-all
jdk/jfr/event/oldobject/TestShenandoah.java 8342951 generic-all
jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64
jdk/jfr/jvm/TestWaste.java 8371630 generic-all
############################################################################
# jdk_internal
############################################################################
# jdk_jpackage
############################################################################
# jdk_foreign
java/foreign/TestBufferStackStress.java 8350455 macosx-all
############################################################################
# Client manual tests
javax/swing/JFileChooser/6698013/bug6698013.java 8024419 macosx-all
javax/swing/JColorChooser/8065098/bug8065098.java 8065647 macosx-all
javax/swing/JTabbedPane/bug4499556.java 8267500 macosx-all
javax/swing/JTabbedPane/TestJTabbedPaneOpaqueColor.java 8345090 windows-all,linux-all
javax/swing/SwingUtilities/TestTextPosInPrint.java 8227025 windows-all
javax/swing/JInternalFrame/bug4134077.java 8184985 windows-all
java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_1.java 7131438,8022539 generic-all
java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_2.java 7131438,8022539 generic-all
java/awt/Modal/WsDisabledStyle/CloseBlocker/CloseBlocker.java 7187741 linux-all,macosx-all
java/awt/xembed/server/TestXEmbedServerJava.java 8001150,8004031 generic-all
java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx-all,linux-all
java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all
java/awt/Frame/FrameStateTest/FrameStateTest.java 8203920 macosx-all,linux-all
java/awt/print/PrinterJob/ScaledText/ScaledText.java 8231226 macosx-all
java/awt/print/PrinterJob/PrintTextTest.java 8148334 macosx-all
java/awt/font/GlyphVector/TestGlyphVectorLayout.java 8354987 generic-all
java/awt/font/TextLayout/TestJustification.java 8250791 macosx-all
java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all
java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all
java/awt/FileDialog/DoubleActionESC.java 8356981 linux-all
java/awt/print/PageFormat/Orient.java 8016055 macosx-all
java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java 8024986 macosx-all,linux-all
java/awt/TextComponent/SelectionAndCaretColor.java 7017622 linux-all
java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter.java 8254841 macosx-all
java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103 linux-all
java/awt/Focus/FrameMinimizeTest/FrameMinimizeTest.java 8016266 linux-x64
java/awt/Frame/SizeMinimizedTest.java 8305915 linux-x64
java/awt/PopupMenu/PopupHangTest.java 8340022 windows-all
java/awt/Focus/MinimizeNonfocusableWindowTest.java 8024487 windows-all
java/awt/List/HandlingKeyEventIfMousePressedTest.java 6848358 macosx-all,windows-all
java/awt/List/ListScrollbarCursorTest.java 8066410 generic-all
java/awt/Checkbox/CheckboxBoxSizeTest.java 8340870 windows-all
java/awt/Checkbox/CheckboxIndicatorSizeTest.java 8340870 windows-all
java/awt/Checkbox/CheckboxNullLabelTest.java 8340870 windows-all
java/awt/dnd/WinMoveFileToShellTest.java 8341665 windows-all
java/awt/Menu/MenuVisibilityTest.java 8161110 macosx-all
java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all
java/awt/Cursor/CursorDragTest/ListDragCursor.java 7177297 macosx-all
############################################################################
# jdk_since_checks
tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java 8354921 generic-all
#############################################################################
# Preview project specific failures go here at the end of the file.
#
# These are NOT failures that occur with the '--enable-preview' option
# specified; those go in the appropriate ProblemList-enable-preview.txt file.
# These are failures that occur WITHOUT the '--enable-preview' option
# specified AND occur because of some issue with preview project code,
# in either implementation or test code.
#############################################################################

131
test/jdk/TEST.ROOT Normal file
View file

@ -0,0 +1,131 @@
#
# Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This file identifies the root of the test-suite hierarchy.
# It also contains test-suite configuration information.
#
# The list of keywords supported in the entire test suite. The
# "intermittent" keyword marks tests known to fail intermittently.
# The "randomness" keyword marks tests using randomness with test
# cases differing from run to run. (A test using a fixed random seed
# would not count as "randomness" by this definition.) Extra care
# should be taken to handle test failures of intermittent or
# randomness tests.
#
# A test flagged with cgroups uses cgroups.
#
# Notes on "client" keywords : headful sound printer multimon
# ===========================================================
#
# These keywords are there to help with test selection so that
# tests that need a particular resource can be selected to run on a system
# with that resource. Conversely "!somekeyword" can be used to exclude tests
# on a system without such a resource.
# Caution: If you are always excluding tests using any of these keywords then you
# are likely missing many important tests.
#
# "headful". A "headful" test requires a graphical environment to meaningfully run.
# This does not have to mean a physical host, since a VM can be configured as headful.
# Tests that are not headful are "headless".
# Note: all manual tests are assumed to be headful and do not need the keyword.
#
# "printer". Not all tests of printing APIs require a printer, but many do.
# So a "printer" test requires a printer to be installed to do anything meaningful.
# Tests may not fail if there is none, instead just silently return.
# But they also may legitimately throw an Exception depending on the test.
# Also printer tests are not necessarily headful, but some are, and some are automated.
#
# "sound". Similarly, not all sound tests require audio devices, but many do.
# A test flagged with key "sound" needs audio devices on the system.
# Also they are not necessarily "headful", since they don't require a display etc.
# But sometimes they may be accompanied by the headful keyword, since sound
# is often linked to access to desktop resources and headful systems are
# also more likely to have audio devices (ie meaning both input and output)
#
# "multimon" should be used in conjunction with headful and is used to identify
# tests which require two displays connected.
keys=headful sound printer multimon \
i18n intermittent randomness cgroups
# Tests that must run in othervm mode
othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/swing javax/print \
com/apple/laf com/apple/eawt com/sun/java/accessibility com/sun/java/swing sanity/client demo/jfc \
javax/management sun/awt sun/java2d javax/xml/jaxp/testng/validation java/lang/ProcessHandle
# Tests that cannot run concurrently
exclusiveAccess.dirs=java/math/BigInteger/largeMemory \
java/rmi/Naming java/util/prefs sun/management/jmxremote \
sun/tools/jstatd sun/security/mscapi java/util/Arrays/largeMemory \
java/util/BitSet/stream javax/rmi java/net/httpclient/websocket \
com/sun/net/httpserver/simpleserver sun/tools/jhsdb
# Group definitions
groups=TEST.groups
# Allow querying of various System properties in @requires clauses
#
# Source files for classes that will be used at the beginning of each test suite run,
# to determine additional characteristics of the system for use with the @requires tag.
# Note: compiled bootlibs classes will be added to BCP.
requires.extraPropDefns = ../jtreg-ext/requires/VMProps.java
requires.extraPropDefns.bootlibs = ../lib/jdk/test/whitebox
requires.extraPropDefns.libs = \
../lib/jdk/test/lib/Platform.java \
../lib/jdk/test/lib/Container.java
requires.extraPropDefns.javacOpts = \
--add-exports java.base/jdk.internal.foreign=ALL-UNNAMED \
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED
requires.extraPropDefns.vmOpts = \
-XX:+UnlockDiagnosticVMOptions \
-XX:+LogVMOutput -XX:-DisplayVMOutput -XX:LogFile=vmprops.flags.final.vm.log \
-XX:+PrintFlagsFinal \
-XX:+WhiteBoxAPI \
--add-exports java.base/jdk.internal.foreign=ALL-UNNAMED \
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED
requires.properties= \
sun.arch.data.model \
java.runtime.name \
java.enablePreview \
vm.flagless \
vm.gc.G1 \
vm.gc.Serial \
vm.gc.Parallel \
vm.gc.Shenandoah \
vm.gc.Epsilon \
vm.gc.Z \
vm.graal.enabled \
vm.compiler1.enabled \
vm.compiler2.enabled \
vm.cds \
vm.cds.write.archived.java.heap \
vm.cds.write.mapped.java.heap \
vm.cds.write.streamed.java.heap \
vm.continuations \
vm.musl \
vm.asan \
vm.ubsan \
vm.debug \
vm.hasSA \
vm.hasJFR \
vm.jvmci \
vm.jvmci.enabled \
vm.jvmti \
vm.cpu.features \
container.support \
systemd.support \
release.implementor \
jdk.containerized \
jdk.foreign.linker \
jlink.runtime.linkable \
jlink.packagedModules \
jdk.static
# Minimum jtreg version
requiredVersion=8.2.1+1
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../ notation to reach them
external.lib.roots = ../../

683
test/jdk/TEST.groups Normal file
View file

@ -0,0 +1,683 @@
# Copyright (c) 2013, 2026, 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.
#
# 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.
#
###############################################################################
#
# All tests
#
all = \
:jdk_all
jdk_all = \
/
###############################################################################
#
# Tiered testing definitions
#
# When adding tests to tier1, make sure they end up in one of the tier1_partX groups
tier1 = \
:tier1_part1 \
:tier1_part2 \
:tier1_part3
tier1_part1 = \
:jdk_lang
tier1_part2 = \
:jdk_util
tier1_part3 = \
:jdk_math \
:jdk_svc_sanity \
:jdk_foreign \
:jdk_vector_sanity \
java/nio/Buffer \
com/sun/crypto/provider/Cipher \
jdk/classfile \
sun/nio/cs/ISO8859x.java
# When adding tests to tier2, make sure they end up in one of the tier2_partX groups
tier2 = \
:tier2_part1 \
:tier2_part2 \
:tier2_part3
# com/sun/crypto/provider/Cipher is in tier1 because of JDK-8132855
tier2_part1 = \
:jdk_security \
-com/sun/crypto/provider/Cipher
# sun/nio/cs/ISO8859x.java and java/nio/Buffer are in tier1 because of JDK-8132854
tier2_part2 = \
:core_tools \
:jdk_io \
:jdk_nio \
-java/nio/Buffer \
-sun/nio/cs/ISO8859x.java \
:jdk_other \
:jdk_text \
:jdk_time
tier2_part3 = \
:jdk_net
# These sub groups of tier3 allow for running certain tests separately from the
# rest. When adding tests to tier3, in most cases they should be added to
# tier3_part1.
tier3 = \
:tier3_part1 \
:tier3_jpackage
tier3_part1 = \
:build \
:jdk_vector \
-:jdk_vector_sanity \
:jdk_rmi \
:jdk_svc \
-:jdk_svc_sanity \
-:svc_tools \
:jdk_since_checks
# The jpackage tests on Windows require permissions that aren't always present
tier3_jpackage = \
:jdk_jpackage
# Everything not in other tiers
tier4 = \
/ \
-:tier1 \
-:tier2 \
-:tier3 \
:jdk_foreign_stress
###############################################################################
#
# Other test definitions; generally smaller granularity than tiers
#
# Build source checking
build = \
build
# java.lang package and VM runtime support
jdk_lang = \
java/lang \
-java/lang/management \
-java/lang/instrument \
sun/invoke \
sun/misc \
sun/reflect \
jdk/internal/reflect \
jdk/lambda \
jdk/internal/loader \
jdk/internal/misc \
jdk/internal/ref \
jdk/internal/jimage \
jdk/internal/math \
jdk/internal/vm \
jdk/modules \
jni/nullCaller
# All of the java.util package
jdk_util = \
:jdk_util_other \
:jdk_collections \
:jdk_concurrent \
:jdk_stream
# All util components not part of some other util category
jdk_util_other = \
java/util \
sun/util \
jdk/internal/util \
-:jdk_collections \
-:jdk_concurrent \
-:jdk_stream
# All collections, core and concurrent
jdk_collections = \
:jdk_collections_core \
:jdk_concurrent
# java.util.concurrent
# Includes concurrent collections plus other stuff
# Maintained by JSR-166 EG (Doug Lea et al)
jdk_concurrent = \
java/util/concurrent
# Java Collections Framework core classes
jdk_collections_core = \
java/util/AbstractCollection \
java/util/AbstractList \
java/util/AbstractMap \
java/util/AbstractSequentialList \
java/util/ArrayDeque \
java/util/ArrayList \
java/util/Arrays \
java/util/BitSet \
java/util/Collection \
java/util/Collections \
java/util/Comparator \
java/util/Deque \
java/util/EnumMap \
java/util/EnumSet \
java/util/HashMap \
java/util/HashSet \
java/util/Hashtable \
java/util/IdentityHashMap \
java/util/Iterator \
java/util/LinkedHashMap \
java/util/LinkedHashSet \
java/util/LinkedList \
java/util/List \
java/util/Map \
java/util/NavigableMap \
java/util/PriorityQueue \
java/util/SequencedCollection \
java/util/TimSort \
java/util/TreeMap \
java/util/Vector \
java/util/WeakHashMap
# java.util.stream (JSR-335)
jdk_stream = \
java/util/Optional \
java/util/function \
java/util/stream
jdk_math = \
java/math
jdk_io = \
java/io
jdk_nio = \
java/nio \
sun/nio \
jdk/nio
jdk_net = \
java/net \
com/sun/net/httpserver \
sun/net \
jdk/net
jdk_time = \
java/time
jdk_rmi = \
java/rmi \
sun/rmi
jdk_security1 = \
java/security
jdk_security2 = \
javax/crypto \
javax/xml/crypto \
com/sun/org/apache/xml/internal/security \
com/sun/crypto
jdk_security3 = \
javax/security \
-javax/security/auth/kerberos \
com/sun/security \
-com/sun/security/jgss \
jdk/security \
sun/security \
-sun/security/krb5 \
-sun/security/jgss \
javax/net
jdk_security4 = \
com/sun/security/jgss \
javax/security/auth/kerberos \
sun/security/krb5 \
sun/security/jgss
jdk_security = \
:jdk_security1 \
:jdk_security2 \
:jdk_security3 \
:jdk_security4
# Tests in this group are manual as they depend on external infra
# and may fail with external reasons, for instance - change in CA test portal.
jdk_security_infra = \
security/infra
jdk_text = \
java/text \
sun/text
jdk_management = \
java/lang/management \
jdk/management \
com/sun/management \
sun/management \
jdk/internal/agent
jdk_instrument = \
java/lang/instrument
jdk_jmx = \
javax/management \
com/sun/jmx
jdk_jdi = \
com/sun/jdi
jdk_native_sanity = \
native_sanity
# java launcher specific tests.
jdk_launcher = \
tools/launcher \
sun/tools
jdk_loom = \
com/sun/management/HotSpotDiagnosticMXBean \
com/sun/management/ThreadMXBean \
jdk/management/VirtualThreadSchedulerMXBean \
java/lang/Thread \
java/lang/ThreadGroup \
java/lang/management/ThreadMXBean \
java/util/concurrent \
java/net/vthread \
java/nio/channels/vthread \
jdk/internal/misc/ThreadFlock \
jdk/internal/vm/Continuation \
jdk/jfr/threading
#
# Tool (and tool API) tests are mostly split into core and svc groups
#
core_tools = \
tools \
-tools/jpackage \
jdk/internal/jrtfs
svc_tools = \
com/sun/tools/attach \
sun/tools \
sun/jvmstat
jdk_tools = \
:core_tools \
:svc_tools \
:jdk_jpackage
jdk_jfr = \
jdk/jfr
jdk_jpackage = \
tools/jpackage
#
# Catch-all for other areas with a small number of tests
#
jdk_other = \
java/sql \
javax/sql \
javax/transaction \
javax/rmi \
javax/naming \
javax/script \
javax/smartcardio \
javax/xml \
-javax/xml/crypto \
jdk/dynalink \
jdk/internal/jline \
com/sun/jndi \
lib/testlibrary
#
# SCTP is its own group as it is highly sensitive to kernel/network config
#
jdk_sctp = \
com/sun/nio/sctp
#
# core group to run all core area tests
#
jdk_core = \
:jdk_lang \
:jdk_util \
:jdk_math \
:jdk_io \
:jdk_nio \
:jdk_net \
:jdk_rmi \
:jdk_time \
:jdk_security \
:jdk_text \
:core_tools \
:jdk_other
#
# svc group to run all serviceability area tests
#
jdk_svc = \
:jdk_management \
:jdk_instrument \
:jdk_jmx \
:jdk_jdi \
:jdk_jfr \
:svc_tools
jdk_foreign = \
java/foreign \
jdk/internal/reflect/CallerSensitive/CheckCSMs.java \
-java/foreign/TestMatrix.java \
-java/foreign/TestUpcallStress.java
jdk_foreign_stress = \
java/foreign/TestUpcallStress.java
jdk_vector = \
jdk/incubator/vector
jdk_vector_sanity = \
jdk/incubator/vector/PreferredSpeciesTest.java \
jdk/incubator/vector/VectorHash.java \
jdk/incubator/vector/VectorRuns.java
#############################
#
# Client area groups
#
jdk_awt = \
java/awt \
com/apple/eawt \
com/apple/laf \
sun/awt
jdk_2d = \
javax/print \
sun/java2d
jdk_beans = \
java/beans
jdk_swing = \
javax/swing \
com/sun/java/swing
jdk_sound = \
javax/sound
jdk_imageio = \
javax/imageio
jdk_accessibility = \
javax/accessibility
jfc_demo = \
demo/jfc
jdk_editpad = \
jdk/editpad
jdk_desktop = \
:jdk_desktop_part1 \
:jdk_desktop_part2 \
:jdk_desktop_part3
jdk_desktop_part1 = \
:jdk_client_sanity \
:jdk_swing \
:jdk_2d \
:jdk_sound \
:jdk_imageio \
:jdk_editpad \
:jfc_demo \
:jdk_accessibility \
:jdk_beans
jdk_desktop_part2 = \
:jdk_awt \
-java/awt/Component \
-java/awt/Modal \
-java/awt/datatransfer \
-java/awt/Window
jdk_desktop_part3 = \
java/awt/Component \
java/awt/Modal \
java/awt/datatransfer \
java/awt/Window
# SwingSet3 tests.
jdk_client_sanity = \
sanity/client/SwingSet
# This test group represents a subset of tests which are expected to
# exercise most of the most commonly used code in Swing applications.
# New failures in this area may be a problem.
jdk_swing_core = \
:jdk_client_sanity \
javax/swing
# The most commonly used printing APIs are included here along with swing core.
jdk_desktop_core = \
:jdk_swing_core \
java/awt/print
###############################################################################
#
# Serviceability sanity groups
#
# These groups specify a subset of Serviceability tests that are supposed to
# guard against breakage of Serviceability features by other component teams.
jdk_svc_sanity = \
:jdk_management_sanity \
:jdk_instrument_sanity \
:jdk_jmx_sanity \
:jdk_jdi_sanity \
:jdk_jfr_sanity \
:svc_tools_sanity
jdk_management_sanity =
jdk_instrument_sanity =
jdk_jmx_sanity =
jdk_jdi_sanity = \
com/sun/jdi/AcceptTimeout.java \
com/sun/jdi/AccessSpecifierTest.java \
com/sun/jdi/AfterThreadDeathTest.java \
com/sun/jdi/ArrayRangeTest.java \
com/sun/jdi/ConstantPoolInfo.java \
com/sun/jdi/CountFilterTest.java \
com/sun/jdi/EarlyReturnNegativeTest.java \
com/sun/jdi/EarlyReturnTest.java \
com/sun/jdi/FieldWatchpoints.java \
com/sun/jdi/FramesTest.java \
com/sun/jdi/InstanceFilter.java \
com/sun/jdi/InterfaceMethodsTest.java \
com/sun/jdi/InvokeTest.java \
com/sun/jdi/LocalVariableEqual.java \
com/sun/jdi/LocationTest.java \
com/sun/jdi/ModificationWatchpoints.java \
com/sun/jdi/MonitorEventTest.java \
com/sun/jdi/MonitorFrameInfo.java \
com/sun/jdi/NullThreadGroupNameTest.java \
com/sun/jdi/PopAndStepTest.java \
com/sun/jdi/PopAsynchronousTest.java \
com/sun/jdi/ProcessAttachTest.java \
com/sun/jdi/ReferrersTest.java \
com/sun/jdi/RequestReflectionTest.java \
com/sun/jdi/ResumeOneThreadTest.java \
com/sun/jdi/RunToExit.java \
com/sun/jdi/SourceNameFilterTest.java \
com/sun/jdi/SuspendAfterDeath.java \
com/sun/jdi/VarargsTest.java \
com/sun/jdi/Vars.java \
com/sun/jdi/redefineMethod/RedefineTest.java \
com/sun/jdi/sde/MangleTest.java \
com/sun/jdi/sde/TemperatureTableTest.java
jdk_jfr_sanity = \
jdk/jfr/api/recording/event/TestLoadEventAfterStart.java \
jdk/jfr/api/recording/state/TestState.java \
jdk/jfr/event/os/TestCPULoad.java \
jdk/jfr/event/allocation/TestObjectAllocationSampleEvent.java \
jdk/jfr/jcmd/TestJcmdStartStopDefault.java \
jdk/jfr/event/io/TestFileStreamEvents.java \
jdk/jfr/event/compiler/TestCompilerCompile.java \
jdk/jfr/event/gc/collection/TestGCGarbageCollectionEvent.java \
jdk/jfr/event/runtime/TestClassLoadEvent.java \
jdk/jfr/event/runtime/TestJavaBlockedEvent.java \
jdk/jfr/event/gc/collection/TestGCWithFasttime.java \
jdk/jfr/event/gc/configuration/TestGCConfigurationEvent.java \
jdk/jfr/event/metadata/TestDefaultConfigurations.java \
jdk/jfr/event/oldobject/TestDFSWithSmallStack.java \
jdk/jfr/startupargs/TestDumpOnExit.java \
jdk/jfr/api/consumer/recordingstream/TestBasics.java
svc_tools_sanity =
#############################
#
# Stable test groups
#
jdk_stable = \
:jdk_core \
:jdk_svc \
:jdk_beans \
:jdk_imageio \
:jdk_sound \
:jdk_sctp \
javax/accessibility \
com/sun/java/swing
needs_g1gc = \
jdk/jfr/event/gc/refstat/TestRefStatEventWithG1ConcurrentMark.java \
jdk/jfr/event/gc/refstat/TestRefStatEventWithG1FullCollection.java \
jdk/jfr/event/gc/refstat/TestRefStatEventWithG1New.java \
jdk/jfr/event/gc/detailed/TestEvacuationFailedEvent.java \
jdk/jfr/event/gc/detailed/TestEvacuationInfoEvent.java \
jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java \
jdk/jfr/event/gc/collection/TestGCCauseWithG1ConcurrentMark.java \
jdk/jfr/event/gc/collection/TestGCCauseWithG1FullCollection.java \
jdk/jfr/event/gc/collection/TestYoungGarbageCollectionEventWithG1New.java \
jdk/jfr/event/gc/collection/TestGCEventMixedWithG1FullCollection.java \
jdk/jfr/event/gc/collection/TestGCEventMixedWithG1ConcurrentMark.java \
jdk/jfr/event/gc/collection/TestG1ParallelPhases.java \
jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1FullCollection.java \
jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1ConcurrentMark.java \
jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventG1.java
# This set of tests will be executed in an ipv6 only environment
jdk_ipv6_only = \
:jdk_net \
:jdk_nio_networkchannel
jdk_nio_networkchannel = \
java/nio/channels/AsyncCloseAndInterrupt.java \
java/nio/channels/AsynchronousServerSocketChannel \
java/nio/channels/AsynchronousSocketChannel \
java/nio/channels/DatagramChannel \
java/nio/channels/ServerSocketChannel \
java/nio/channels/SocketChannel \
java/nio/channels/Selector \
java/nio/channels/etc
jdk_core_manual = \
:jdk_core_manual_no_input \
:jdk_security_manual_no_input \
:jdk_core_manual_interactive \
:jdk_security_manual_interactive
jdk_core_manual_no_input = \
java/net/HugeDataTransferTest.java \
java/net/httpclient/BodyProcessorInputStreamTest.java \
java/net/httpclient/HttpInputStreamTest.java \
java/util/zip/ZipFile/TestZipFile.java \
javax/net/ssl/compatibility/AlpnTest.java \
javax/net/ssl/compatibility/BasicConnectTest.java \
javax/net/ssl/compatibility/HrrTest.java \
javax/net/ssl/compatibility/SniTest.java \
jdk/nio/zipfs/LargeCompressedEntrySizeTest.java \
java/util/ArrayList/Bug8146568.java \
java/util/Vector/Bug8148174.java \
com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java \
com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java \
com/sun/net/httpserver/simpleserver/DocRootDirPermissionsWinTest.java \
javax/xml/jaxp/datatype/8033980/GregorianCalAndDurSerDataUtil.java \
java/util/zip/ZipFile/CenSizeMaximum.java
jdk_security_manual_no_input = \
:jdk_security_infra \
com/sun/crypto/provider/Cipher/AEAD/GCMIncrementByte4.java \
com/sun/crypto/provider/Cipher/AEAD/GCMIncrementDirect4.java \
sun/security/smartcardio/TestChannel.java \
sun/security/smartcardio/TestConnect.java \
sun/security/smartcardio/TestConnectAgain.java \
sun/security/smartcardio/TestControl.java \
sun/security/smartcardio/TestDefault.java \
sun/security/smartcardio/TestDirect.java \
sun/security/smartcardio/TestExclusive.java \
sun/security/smartcardio/TestMultiplePresent.java \
sun/security/smartcardio/TestPresent.java \
sun/security/smartcardio/TestTransmit.java \
sun/security/tools/jarsigner/compatibility/Compatibility.java \
sun/security/tools/keytool/ListKeyChainStore.java
jdk_core_manual_interactive = \
com/sun/jndi/dns/Test6991580.java \
java/util/TimeZone/DefaultTimeZoneTest.java \
java/nio/MappedByteBuffer/PmemTest.java \
java/rmi/registry/nonLocalRegistry/NonLocalRegistryTest.java \
java/rmi/registry/nonLocalRegistry/NonLocalSkeletonTest.java \
java/foreign/TestMatrix.java \
java/nio/channels/FileChannel/BlockDeviceSize.java
jdk_security_manual_interactive = \
sun/security/tools/keytool/i18n.java \
com/sun/security/auth/callback/TextCallbackHandler/Password.java \
sun/security/krb5/config/native/TestDynamicStore.java \
sun/security/tools/keytool/EchoPassword.java
# Test sets for running inside container environment
jdk_containers_extended = \
:jdk_io \
:jdk_nio \
:jdk_svc
jdk_core_no_security = \
:jdk_core \
-:jdk_security
# Set of tests for `@since` checks in source code documentation
jdk_since_checks = \
tools/sincechecker/

View file

@ -0,0 +1,340 @@
/*
* Copyright (c) 2019, 2025, 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.
*
* 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.
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static java.util.Comparator.comparing;
/*
* @test
* @bug 8226346
* @summary Check all output files for absolute path fragments
* @requires !vm.debug
* @comment ASAN keeps the 'unwanted' paths in the binaries because of its build options
* @requires !vm.asan
* @run main AbsPathsInImage
*/
public class AbsPathsInImage {
// Set this property on command line to scan an alternate dir or file:
// JTREG=JAVA_OPTIONS=-Djdk.test.build.AbsPathInImage.dir=/path/to/dir
public static final String DIR_PROPERTY = "jdk.test.build.AbsPathsInImage.dir";
private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows");
private static final boolean IS_LINUX = System.getProperty("os.name").toLowerCase().contains("linux");
private static final int DEFAULT_BUFFER_SIZE = 8192;
private static List<byte[]> searchPatterns = new ArrayList<>();
private static List<int[]> prefixTables = new ArrayList<>();
private boolean matchFound = false;
record Match(int begin, int end) { }
public static void main(String[] args) throws Exception {
String jdkPathString = System.getProperty("test.jdk");
Path jdkHome = Paths.get(jdkPathString);
Path dirToScan = jdkHome;
String overrideDir = System.getProperty(DIR_PROPERTY);
if (overrideDir != null) {
dirToScan = Paths.get(overrideDir);
}
String buildWorkspaceRoot = null;
String buildOutputRoot = null;
String testImageDirString = System.getenv("TEST_IMAGE_DIR");
if (testImageDirString != null) {
Path testImageDir = Paths.get(testImageDirString);
Path buildInfoPropertiesFile = testImageDir.resolve("build-info.properties");
System.out.println("Getting patterns from " + buildInfoPropertiesFile.toString());
Properties buildInfoProperties = new Properties();
try (InputStream inStream = Files.newInputStream(buildInfoPropertiesFile)) {
buildInfoProperties.load(inStream);
}
buildWorkspaceRoot = buildInfoProperties.getProperty("build.workspace.root");
buildOutputRoot = buildInfoProperties.getProperty("build.output.root");
} else {
System.out.println("Getting patterns from local environment");
// Try to resolve the workspace root based on the jtreg test root dir
String testRootDirString = System.getProperty("test.root");
if (testRootDirString != null) {
Path testRootDir = Paths.get(testRootDirString);
// Remove /test/jdk suffix
buildWorkspaceRoot = testRootDir.getParent().getParent().toString();
}
// Remove /jdk
Path buildOutputRootPath = jdkHome.getParent();
if (buildOutputRootPath.endsWith("images")) {
buildOutputRootPath = buildOutputRootPath.getParent();
}
buildOutputRoot = buildOutputRootPath.toString();
}
if (buildWorkspaceRoot == null) {
throw new Error("Could not find workspace root, test cannot run");
}
if (buildOutputRoot == null) {
throw new Error("Could not find build output root, test cannot run");
}
// Validate the root paths
if (!Paths.get(buildWorkspaceRoot).isAbsolute()) {
throw new Error("Workspace root is not an absolute path: " + buildWorkspaceRoot);
}
if (!Paths.get(buildOutputRoot).isAbsolute()) {
throw new Error("Output root is not an absolute path: " + buildOutputRoot);
}
expandPatterns(buildWorkspaceRoot);
expandPatterns(buildOutputRoot);
createPrefixTables();
System.out.println("Looking for:");
for (byte[] searchPattern : searchPatterns) {
System.out.println(new String(searchPattern));
}
System.out.println();
AbsPathsInImage absPathsInImage = new AbsPathsInImage();
absPathsInImage.scanFiles(dirToScan);
if (absPathsInImage.matchFound) {
throw new Exception("Test failed");
}
}
/**
* Add path pattern to list of patterns to search for. Create all possible
* variants depending on platform.
*/
private static void expandPatterns(String pattern) {
if (IS_WINDOWS) {
String forward = pattern.replace('\\', '/');
String back = pattern.replace('/', '\\');
if (pattern.charAt(1) == ':') {
String forwardUpper = String.valueOf(pattern.charAt(0)).toUpperCase() + forward.substring(1);
String forwardLower = String.valueOf(pattern.charAt(0)).toLowerCase() + forward.substring(1);
String backUpper = String.valueOf(pattern.charAt(0)).toUpperCase() + back.substring(1);
String backLower = String.valueOf(pattern.charAt(0)).toLowerCase() + back.substring(1);
searchPatterns.add(forwardUpper.getBytes());
searchPatterns.add(forwardLower.getBytes());
searchPatterns.add(backUpper.getBytes());
searchPatterns.add(backLower.getBytes());
} else {
searchPatterns.add(forward.getBytes());
searchPatterns.add(back.getBytes());
}
} else {
searchPatterns.add(pattern.getBytes());
}
}
/**
* The failure function for KMP. Returns the correct index in the pattern to jump
* back to when encountering a mismatched character. Used in both
* createPrefixTables (pre-processing) and scanBytes (matching).
*/
private static int getPrefixIndex(int patternIdx, int state, byte match) {
if (state == 0) {
return 0;
}
byte[] searchPattern = searchPatterns.get(patternIdx);
int[] prefixTable = prefixTables.get(patternIdx);
int i = prefixTable[state - 1];
while (i > 0 && searchPattern[i] != match) {
i = prefixTable[i - 1];
}
return searchPattern[i] == match ? i + 1 : i;
}
/**
* Pre-processing string patterns for Knuth–Morris–Pratt (KMP) search algorithm.
* Lookup tables of longest prefixes at each given index are created for each
* search pattern string. These tables are later used in scanBytes during matching
* as lookups for failure state transitions.
*/
private static void createPrefixTables() {
for (int patternIdx = 0; patternIdx < searchPatterns.size(); patternIdx++) {
int patternLen = searchPatterns.get(patternIdx).length;
int[] prefixTable = new int[patternLen];
prefixTables.add(prefixTable);
for (int i = 1; i < patternLen; i++) {
prefixTable[i] = getPrefixIndex(patternIdx, i, searchPatterns.get(patternIdx)[i]);
}
}
}
private void scanFiles(Path root) throws IOException {
Files.walkFileTree(root, new SimpleFileVisitor<>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
String dirName = dir.toString();
if (dirName.endsWith(".dSYM")) {
return FileVisitResult.SKIP_SUBTREE;
}
return super.preVisitDirectory(dir, attrs);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String fileName = file.toString();
if (Files.isSymbolicLink(file)) {
return super.visitFile(file, attrs);
} else if ((fileName.endsWith(".debuginfo") && !IS_LINUX) || fileName.endsWith(".pdb")) {
// Do nothing
} else if (fileName.endsWith(".zip")) {
scanZipFile(file);
} else {
scanFile(file);
}
return super.visitFile(file, attrs);
}
});
}
private void scanFile(Path file) throws IOException {
List<Match> matches;
try (InputStream inputStream = Files.newInputStream(file)) {
matches = scanBytes(inputStream);
}
// test succeeds
if (matches.size() == 0) {
return;
}
// test fails; pay penalty and re-scan file for debug output
try (InputStream inputStream = Files.newInputStream(file)) {
printDebugOutput(inputStream, matches, file + ":");
}
}
private void scanZipFile(Path zipFile) throws IOException {
List<List<Match>> entryMatches = new ArrayList<>();
boolean found = false;
ZipEntry zipEntry;
try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) {
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
List<Match> matches = scanBytes(zipInputStream);
if (matches.size() > 0) {
entryMatches.add(matches);
found = true;
} else {
entryMatches.add(null);
}
}
}
// test succeeds
if (!found) {
return;
}
// test fails
try (ZipInputStream zipInputStream = new ZipInputStream(Files.newInputStream(zipFile))) {
int i = 0;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
List<Match> matches = entryMatches.get(i);
i++;
if (matches != null) {
printDebugOutput(zipInputStream, matches, zipFile + ", " + zipEntry.getName() + ":");
}
}
}
}
/**
* Scans each byte until encounters a match with one of searchPatterns. Uses KMP to
* perform matches. Keep track of current matched index (states) for each search
* pattern. At each given byte, update states accordingly (increment if match or
* failure function transition if mismatch). Returns a list of Match objects.
*/
private List<Match> scanBytes(InputStream input) throws IOException {
List<Match> matches = new ArrayList<>();
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
int[] states = new int[searchPatterns.size()];
int fileIdx = 0;
int bytesRead, patternLen;
while ((bytesRead = input.read(buf)) != -1) {
for (int bufIdx = 0; bufIdx < bytesRead; bufIdx++, fileIdx++) {
byte datum = buf[bufIdx];
for (int i = 0; i < searchPatterns.size(); i++) {
patternLen = searchPatterns.get(i).length;
if (datum != searchPatterns.get(i)[states[i]]) {
states[i] = getPrefixIndex(i, states[i], datum);
} else if (++states[i] == patternLen) {
// technically at last match, state should reset according to failure function
// but in original test, matching didn't search same string for multiple matches
states[i] = 0;
matches.add(new Match(fileIdx - patternLen + 1, fileIdx));
break;
}
}
}
}
return matches;
}
/**
* In original test, failed test output would backtrack to last non-ascii byte on
* matched pattern. This is incompatible with the new buffered approach (and a
* proper solution requires a 2nd dynamic buffer). Instead, on failed test case,
* files are scanned a 2nd time to print debug output. Failed runs will pay
* additional performance/space penalty, but passing runs are faster.
*/
private void printDebugOutput(InputStream input, List<Match> matches, final String HEADER) throws IOException{
matchFound = true;
System.out.println(HEADER);
matches.sort(comparing(Match::begin));
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
int matchIdx = 0;
int fileIdx = 0;
int bytesRead;
while (matchIdx < matches.size() && (bytesRead = input.read(buf)) != -1) {
for (int i = 0; matchIdx < matches.size() && i < bytesRead; i++, fileIdx++) {
byte datum = buf[i];
if (datum >= 32 && datum <= 126) {
output.write(datum);
} else if (fileIdx < matches.get(matchIdx).begin()) {
output.reset();
} else if (fileIdx > matches.get(matchIdx).end()) {
System.out.println(output.toString());
output.reset();
// This imperfect as incorrect in edge cases with patterns containing non-ascii?
// but high-accuracy not priority + output still legible and useful
for (; matchIdx < matches.size() && matches.get(matchIdx).end() < fileIdx; matchIdx++);
} else {
output.write(datum);
}
}
}
System.out.println();
}
}

View file

@ -0,0 +1,244 @@
/*
* Copyright (c) 2026 SAP SE. All rights reserved.
* Copyright (c) 2026, 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.
*
* 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.
*/
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import jdk.test.lib.Platform;
/*
* @test
* @summary Check for unwanted files (types/extensions) in the jdk image
* @library /test/lib
* @requires !vm.debug
* @run main CheckFiles
*/
public class CheckFiles {
// Set this property on command line to scan an alternate dir or file:
// JTREG=JAVA_OPTIONS=-Djdk.test.build.CheckFiles.dir=/path/to/dir
public static final String DIR_PROPERTY = "jdk.test.build.CheckFiles.dir";
private static boolean isGpl(Path myFile) {
if (myFile == null || !Files.exists(myFile)) {
return false;
}
try {
String firstLine = Files.readAllLines(myFile).stream()
.findFirst().orElse("");
return firstLine.contains("The GNU General Public License (GPL)");
} catch (IOException e) {
return false;
}
}
public static void main(String[] args) throws Exception {
String jdkPathString = System.getProperty("test.jdk");
Path jdkHome = Paths.get(jdkPathString);
Path mainDirToScan = jdkHome;
String overrideDir = System.getProperty(DIR_PROPERTY);
if (overrideDir != null) {
mainDirToScan = Paths.get(overrideDir);
}
System.out.println("Main directory to scan:" + mainDirToScan);
Path binDir = mainDirToScan.resolve("bin");
Path libDir = mainDirToScan.resolve("lib");
Path includeDir = mainDirToScan.resolve("include");
Path jmodsDir = mainDirToScan.resolve("jmods");
System.out.println("Bin directory to scan:" + binDir);
ArrayList<String> allowedEndingsBinDir = new ArrayList<>();
// UNIX - no extensions are allowed; Windows : .dll, .exe, .pdb, .jsa
if (Platform.isWindows()) {
allowedEndingsBinDir.add(".dll");
allowedEndingsBinDir.add(".exe");
allowedEndingsBinDir.add(".pdb");
allowedEndingsBinDir.add(".jsa");
}
boolean binDirRes = scanFiles(binDir, allowedEndingsBinDir);
System.out.println("Lib directory to scan:" + libDir);
ArrayList<String> allowedEndingsLibDir = new ArrayList<>();
allowedEndingsLibDir.add(".jfc"); // jfr config files
allowedEndingsLibDir.add("cacerts");
allowedEndingsLibDir.add("blocked.certs");
allowedEndingsLibDir.add("public_suffix_list.dat");
allowedEndingsLibDir.add("classlist");
allowedEndingsLibDir.add("fontconfig.bfc");
allowedEndingsLibDir.add("fontconfig.properties.src");
allowedEndingsLibDir.add("ct.sym");
allowedEndingsLibDir.add("jrt-fs.jar");
allowedEndingsLibDir.add("jvm.cfg");
allowedEndingsLibDir.add("modules");
allowedEndingsLibDir.add("psfontj2d.properties");
allowedEndingsLibDir.add("psfont.properties.ja");
allowedEndingsLibDir.add("src.zip");
allowedEndingsLibDir.add("tzdb.dat");
allowedEndingsLibDir.add("javafx-swt.jar");
allowedEndingsLibDir.add("javafx.properties");
if (Platform.isWindows()) {
allowedEndingsLibDir.add(".lib");
allowedEndingsLibDir.add("tzmappings");
} else {
allowedEndingsLibDir.add("jexec");
allowedEndingsLibDir.add("jspawnhelper");
allowedEndingsLibDir.add(".jsa");
if (Platform.isOSX()) {
allowedEndingsLibDir.add("shaders.metallib");
allowedEndingsLibDir.add(".dylib");
} else {
allowedEndingsLibDir.add(".so");
}
if (Platform.isAix()) {
allowedEndingsLibDir.add("tzmappings");
}
}
boolean libDirRes = scanFiles(libDir, allowedEndingsLibDir);
if (binDirRes) {
System.out.println("Bin directory scan successful.");
} else {
throw new Error("bin dir scan failed");
}
if (libDirRes) {
System.out.println("Lib directory scan successful.");
} else {
throw new Error("lib dir scan failed");
}
if (Files.isDirectory(includeDir)) {
System.out.println("Include directory to scan:" + includeDir);
ArrayList<String> allowedEndingsIncludeDir = new ArrayList<>();
allowedEndingsIncludeDir.add(".h");
allowedEndingsIncludeDir.add(".hpp");
boolean includeDirRes = scanFiles(includeDir, allowedEndingsIncludeDir);
if (includeDirRes) {
System.out.println("Include directory scan successful.");
} else {
throw new Error("include dir scan failed");
}
}
// when enabling "JEP 493: Linking Run-Time Images without JMODs" we do not
// have the jmods folder at all, so first test the presence of the folder
if (Files.isDirectory(jmodsDir)) {
System.out.println("Jmods directory to scan:" + jmodsDir);
ArrayList<String> allowedEndingsJmodsDir = new ArrayList<>();
allowedEndingsJmodsDir.add(".jmod");
boolean jmodsDirRes = scanFiles(jmodsDir, allowedEndingsJmodsDir);
if (jmodsDirRes) {
System.out.println("Jmods directory scan successful.");
} else {
throw new Error("jmods dir scan failed");
}
}
Path legalDir = mainDirToScan.resolve("legal");
Path javabaseLicenseFile = mainDirToScan.resolve("legal/java.base/LICENSE");
if (isGpl(javabaseLicenseFile)) { // for now check only legal dir of GPL based images; other ones might have other content
System.out.println("GPL info found in java.base LICENSE file");
ArrayList<String> allowedEndingsLegalDir = new ArrayList<>();
allowedEndingsLegalDir.add(".md");
allowedEndingsLegalDir.add("ADDITIONAL_LICENSE_INFO");
allowedEndingsLegalDir.add("ASSEMBLY_EXCEPTION");
allowedEndingsLegalDir.add("LICENSE");
ArrayList<String> requiredFilesInLegalSubdirs = new ArrayList<>();
requiredFilesInLegalSubdirs.add("LICENSE");
requiredFilesInLegalSubdirs.add("ADDITIONAL_LICENSE_INFO");
requiredFilesInLegalSubdirs.add("ASSEMBLY_EXCEPTION");
System.out.println("Legal directory to scan:" + legalDir);
try (DirectoryStream<Path> stream = Files.newDirectoryStream(legalDir)) {
for (Path subfolder : stream) {
if (Files.isDirectory(subfolder)) {
System.out.println("Checking legal dir subfolder for required files: " + subfolder.getFileName());
for (String fileName : requiredFilesInLegalSubdirs) {
Path filePath = subfolder.resolve(fileName);
if (Files.exists(filePath)) {
System.out.println(" Found " + fileName);
} else {
System.out.println(" Missing " + fileName);
throw new Error("legal dir scan for required files failed");
}
}
}
}
}
boolean legalDirRes = scanFiles(legalDir, allowedEndingsLegalDir);
if (legalDirRes) {
System.out.println("Legal directory scan successful.");
} else {
throw new Error("Legal dir scan failed");
}
}
}
private static boolean scanFiles(Path root, ArrayList<String> allowedEndings) throws IOException {
AtomicBoolean badFileFound = new AtomicBoolean(false);
Files.walkFileTree(root, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String fullFileName = file.toString();
String fileName = file.getFileName().toString();
System.out.println(" visiting file:" + fullFileName);
checkFile(fileName, allowedEndings);
return super.visitFile(file, attrs);
}
private void checkFile(String name, ArrayList<String> allowedEndings) {
if (allowedEndings.isEmpty()) { // no file extensions allowed
int lastDot = name.lastIndexOf('.');
if (lastDot > 0) {
System.out.println(" --> ERROR this file is not allowed:" + name);
badFileFound.set(true);
}
} else {
boolean allowed = allowedEndings.stream().anyMatch(name::endsWith);
if (! allowed) {
System.out.println(" --> ERROR this file is not allowed:" + name);
badFileFound.set(true);
}
}
}
});
return !badFileFound.get();
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2018, 2023, 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.
*
* 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.
*/
/*
* @test
* @bug 8193660 8303476
* @summary Check SOURCE line and JAVA_RUNTIME_VERSION in "release" file
* @run main CheckReleaseFile
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CheckReleaseFile {
public static final String SRC_HASH_REGEXP = ":git:[a-z0-9]*\\+?";
public static void main(String args[]) throws IOException {
String jdkPath = System.getProperty("test.jdk");
String runtime = System.getProperty("java.runtime.name");
System.out.println("JDK Path : " + jdkPath);
System.out.println("Runtime Name : " + runtime);
checkReleaseFile(Path.of(jdkPath));
}
private static void checkReleaseFile(Path javaHome) throws IOException {
String source = null;
String runtimeVersion = null;
Path releaseFile = javaHome.resolve("release");
// open the stream to read in for Entries
try (BufferedReader buffRead = Files.newBufferedReader(releaseFile)) {
// this is the string read
String readIn;
// let's read some strings!
while ((readIn = buffRead.readLine()) != null) {
readIn = readIn.trim();
// throw out blank lines
if (readIn.length() == 0)
continue;
// grab SOURCE line
if (readIn.startsWith("SOURCE=")) {
source = readIn;
continue;
}
// grab JAVA_RUNTIME_VERSION line
if (readIn.startsWith("JAVA_RUNTIME_VERSION=")) {
runtimeVersion = readIn;
continue;
}
}
}
// was SOURCE even found?
if (source == null) {
throw new RuntimeException("SOURCE line was not found!");
}
checkSource(source);
if (runtimeVersion == null) {
throw new RuntimeException("JAVA_RUNTIME_VERSION line was not found!");
}
String expected = "JAVA_RUNTIME_VERSION=\"" + Runtime.version() + "\"";
if (!expected.equals(runtimeVersion)) {
throw new RuntimeException("Mismatched runtime version: " +
runtimeVersion + " expected: " + expected);
}
}
private static void checkSource(String source) {
System.out.println("The source string found: " + source);
// Extract the value of SOURCE=
Pattern valuePattern = Pattern.compile("SOURCE=\"(.*)\"");
Matcher valueMatcher = valuePattern.matcher(source);
if (!valueMatcher.matches()) {
throw new RuntimeException("SOURCE string has bad format, should be SOURCE=\"<value>\"");
}
String valueString = valueMatcher.group(1);
String[] values = valueString.split(" ");
// First value MUST start with ".:" regardless of Oracle or OpenJDK
String rootRegexp = "\\." + SRC_HASH_REGEXP;
if (!values[0].matches(rootRegexp)) {
throw new RuntimeException("The test failed, first element did not match regexp: " + rootRegexp);
}
// If it's an Oracle build, it can be either OpenJDK or OracleJDK. Other
// builds may have any number of additional elements in any format.
String runtime = System.getProperty("java.runtime.name");
String vendor = System.getProperty("java.vendor");
if (runtime.contains("OpenJDK") && vendor.contains("Oracle Corporation")) {
System.out.println("Oracle built OpenJDK, verifying SOURCE format");
if (values.length != 1) {
throw new RuntimeException("The test failed, wrong number of elements in SOURCE list." +
" Should be 1 for Oracle built OpenJDK.");
}
} else {
System.out.println("Not Oracle built OpenJDK, skipping further SOURCE verification");
}
// Everything was fine
System.out.println("The test passed!");
}
}

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2018, 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.
*
* 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.
*/
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* @test
* @requires release.implementor == "Oracle Corporation"
* @modules jdk.jlink/jdk.tools.jimage
* @summary Oracle builds of OpenJDK should only contain english, chinese and
* japanese translations
*/
public class VerifyTranslations {
/**
* The set of translations we want to see in an Oracle built image
*/
private static final Set<String> VALID_TRANSLATION_SUFFIXES = Set.of(
"_en", "_en_US", "_en_US_POSIX", "_ja", "_zh_CN", "_de"
);
/**
* This regexp will not match locales with 3 letter lang strings because
* doing so would trigger a ton of false positives all over the source
* tree. This is ok for now but is a potential future flaw in the test.
*/
private static final String BASE_LOCALE_REGEXP
= "(_[a-z]{2}(_[A-Z][a-z]{3})?(_([A-Z]{2})|([0-9]{3}))?(_[a-zA-Z]+)?)";
public static void main(String[] args) {
String jdkPath = System.getProperty("test.jdk");
String modulesFile = jdkPath + "/lib/modules";
// Run jimage tool to extract list of all classes and resources in the jdk
StringWriter output = new StringWriter();
jdk.tools.jimage.Main.run(new String[] { "list", modulesFile }, new PrintWriter(output));
Pattern classesLocalePattern = Pattern.compile(BASE_LOCALE_REGEXP + "\\.(class|properties)");
boolean failed = false;
String module = "";
for (String line : output.toString().split("\n")) {
if (line.startsWith("Module: ")) {
module = line.substring(8).trim();
}
// We do not filter resources in jdk.localedata
if (!module.equals("jdk.localedata")) {
Matcher matcher = classesLocalePattern.matcher(line);
if (matcher.find()) {
if (!VALID_TRANSLATION_SUFFIXES.contains(matcher.group(1))) {
System.out.println("Unsupported translation found in lib/modules: "
+ module + "/" + line.trim());
failed = true;
}
}
}
}
// Check all files in src.zip
Pattern sourceLocalePattern = Pattern.compile(BASE_LOCALE_REGEXP + "\\.java");
String srcZip = jdkPath + "/lib/src.zip";
try (ZipInputStream srcZipInput = new ZipInputStream(
new BufferedInputStream(new FileInputStream(srcZip)))) {
ZipEntry entry;
while ((entry = srcZipInput.getNextEntry()) != null) {
String name = entry.getName();
if (!name.startsWith("jdk.localedata")) {
Matcher matcher = sourceLocalePattern.matcher(name);
if (matcher.find()) {
if (!VALID_TRANSLATION_SUFFIXES.contains(matcher.group(1))) {
System.out.println("Unsupported translation found in lib/src.zip: " + name);
failed = true;
}
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
if (failed) {
throw new RuntimeException("lib/modules contains unsupported translations");
}
}
}

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2013, 2021, 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.
*
* 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.
*/
/**
* @test
* @key headful
* @bug 8007267 8233648
* @summary [macosx] com.apple.eawt.Application.setDefaultMenuBar is not working
* @requires (os.family == "mac")
* @modules java.desktop/com.apple.eawt
* @run main/othervm DefaultMenuBarTest
*/
import java.awt.Robot;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.lang.reflect.Method;
public class DefaultMenuBarTest {
static KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.META_MASK);
static volatile int listenerCallCounter = 0;
public static void main(String[] args) throws Exception {
if (!System.getProperty("os.name").contains("OS X")) {
System.out.println("This test is for MacOS only. Automatically passed on other platforms.");
return;
}
System.setProperty("apple.laf.useScreenMenuBar", "true");
SwingUtilities.invokeAndWait(DefaultMenuBarTest::createAndShowGUI);
Robot robot = new Robot();
robot.setAutoDelay(100);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_META);
robot.keyPress(ks.getKeyCode());
robot.keyRelease(ks.getKeyCode());
robot.keyRelease(KeyEvent.VK_META);
robot.waitForIdle();
if (listenerCallCounter != 1) {
throw new Exception("Test failed: ActionListener either wasn't called or was called more than once");
}
}
private static void createAndShowGUI() {
JMenu menu = new JMenu("File");
JMenuItem newItem = new JMenuItem("Open");
newItem.setAccelerator(ks);
newItem.addActionListener(e -> listenerCallCounter++);
menu.add(newItem);
JMenuBar defaultMenu = new JMenuBar();
defaultMenu.add(menu);
// Application.getApplication().setDefaultMenuBar(defaultMenu);
try {
Class appClass = Class.forName("com.apple.eawt.Application");
if (appClass != null) {
Method method = appClass.getMethod("getApplication");
if (method != null) {
Object app = method.invoke(null, new Object[]{});
if (app != null) {
method = appClass.getMethod("setDefaultMenuBar", new Class[]{JMenuBar.class});
if (method != null) {
method.invoke(app, new Object[]{defaultMenu});
}
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,2 @@
modules=java.desktop

View file

@ -0,0 +1,209 @@
/*
* Copyright (c) 2025, 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.
*
* 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.
*/
/**
* @test
* @key headful
* @bug 8344697
* @summary Default button in AquaRootPaneUI should paint special background color
* @requires (os.family == "mac")
* @run main RootPaneDefaultButtonTest
*/
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
/**
* This presents two dialogs, each with two possible default buttons. The
* background color of the default button should change based on which radio
* button is selected.
* <p>
* Note we've never expected this test to fail. This test was introduced
* because the resolution to JDK-8344697 involved removing code, and we wanted
* to double-check that the removed code didn't negatively affect how default
* buttons are repainted.
*/
public class RootPaneDefaultButtonTest {
static class TestDialog extends JDialog {
JButton button1 = new JButton("Button 1");
JButton button2 = new JButton("Button 2");
TestDialog() {
getContentPane().setLayout(new BorderLayout());
getContentPane().add(createPushButtonRow(), BorderLayout.SOUTH);
setUndecorated(true);
pack();
}
private JPanel createPushButtonRow() {
JPanel p = new JPanel(new GridLayout(1, 2));
p.add(button1);
p.add(button2);
p.setBorder(new EmptyBorder(5,5,5,5));
return p;
}
}
/**
* We want 2 dialogs: one in the foreground and one not in the foreground
*/
static class TestScene {
boolean isButton1Default, isButton2Default;
TestScene(boolean isButton1Default, boolean isButton2Default) {
this.isButton1Default = isButton1Default;
this.isButton2Default = isButton2Default;
}
void run() throws Exception {
SwingUtilities.invokeAndWait(() -> {
System.out.println(
"Testing isButton1Default = " + isButton1Default +
" isButton2Default = " + isButton2Default);
TestDialog window1 = new TestDialog();
TestDialog window2 = new TestDialog();
if (isButton1Default) {
window1.getRootPane().setDefaultButton(window1.button1);
}
if (isButton2Default) {
window1.getRootPane().setDefaultButton(window1.button2);
}
Rectangle r1 = new Rectangle(0, 100,
window1.getWidth(), window1.getHeight());
window1.setBounds(r1);
Rectangle r2 = new Rectangle((int) (r1.getMaxX() + 10), 100,
window2.getWidth(), window2.getHeight());
window2.setBounds(r2);
window1.setVisible(true);
window2.setVisible(true);
Rectangle sum = new Rectangle();
sum.add(r1);
sum.add(r2);
BufferedImage bi = new BufferedImage(sum.width, sum.height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
window1.paint(g.create(r1.x, r1.y, r1.width, r1.height));
window2.paint(g.create(r2.x, r2.y, r2.width, r2.height));
g.dispose();
// the exact colors may change depending on your system's
// appearance. Depending on how you've configured "Appearance"
// in the System Settings app: the default button may be blue
// (the default), red, purple, etc. So instead of checking for
// a specific color: we'll make sure 3-4 are the same color,
// and one is significantly different.
Color defaultColor = null;
Color nonDefaultColor = null;
JButton[] buttons = new JButton[] {window1.button1,
window1.button2, window2.button1, window2.button2};
try {
for (int a = 0; a < buttons.length; a++) {
try {
JButton b = buttons[a];
Point p = b.getLocationOnScreen();
int x = p.x + 20;
int y = p.y + 10;
Color c = new Color(bi.getRGB(x - sum.x, y - sum.y));
if (b.isDefaultButton()) {
if (defaultColor == null) {
defaultColor = c;
} else {
throw new IllegalStateException(
"there should only be at most 1 " +
"default button");
}
} else {
if (nonDefaultColor == null) {
nonDefaultColor = c;
} else if (!isSimilar(nonDefaultColor, c)) {
throw new IllegalStateException(
"these two colors should match: " + c +
", " + nonDefaultColor);
}
}
if (defaultColor != null && nonDefaultColor != null &&
isSimilar(defaultColor, nonDefaultColor)) {
throw new IllegalStateException(
"The default button and non-default " +
"buttons should look " +
"different: " + defaultColor +
" matches " + nonDefaultColor);
}
} catch(Exception e) {
System.err.println("a = " + a);
throw e;
}
}
} finally {
System.out.println("defaultColor = " + defaultColor +
" nonDefaultColor = " + nonDefaultColor);
window1.dispose();
window2.dispose();
}
System.out.println("Test passed successfully\n");
});
}
}
private static boolean isSimilar(Color c1, Color c2) {
if (Math.abs(c1.getRed() - c2.getRed()) > 15) {
return false;
}
if (Math.abs(c1.getGreen() - c2.getGreen()) > 15) {
return false;
}
if (Math.abs(c1.getBlue() - c2.getBlue()) > 15) {
return false;
}
return true;
}
public static void main(String[] args) throws Exception {
if (!System.getProperty("os.name").contains("OS X")) {
System.out.println("This test is for MacOS only.");
return;
}
new TestScene(true, false).run();
new TestScene(false, true).run();
new TestScene(false, false).run();
}
}

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2016, 2018, 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.
*
* 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.
*/
/**
* @test
* @key headful
* @bug 8158325 8180821 8202878
* @summary Memory leak in com.apple.laf.ScreenMenu: removed JMenuItems are still referenced
* @requires (os.family == "mac")
* @library /javax/swing/regtesthelpers
* @build Util
* @run main/timeout=300/othervm -Xmx16m ScreenMenuMemoryLeakTest
*/
import java.awt.EventQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.WindowConstants;
public class ScreenMenuMemoryLeakTest {
private static WeakReference<JMenuItem> sMenuItem;
private static JFrame sFrame;
private static JMenu sMenu;
public static void main(String[] args) throws InvocationTargetException, InterruptedException {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
System.setProperty("apple.laf.useScreenMenuBar", "true");
showUI();
}
});
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
removeMenuItemFromMenu();
}
});
Util.generateOOME();
JMenuItem menuItem = sMenuItem.get();
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
sFrame.dispose();
}
});
if (menuItem != null) {
throw new RuntimeException("The menu item should have been GC-ed");
}
}
private static void showUI() {
sFrame = new JFrame();
sFrame.add(new JLabel("Some dummy content"));
JMenuBar menuBar = new JMenuBar();
sMenu = new JMenu("Menu");
JMenuItem item = new JMenuItem("Item");
sMenu.add(item);
sMenuItem = new WeakReference<>(item);
menuBar.add(sMenu);
sFrame.setJMenuBar(menuBar);
sFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
sFrame.pack();
sFrame.setVisible(true);
}
private static void removeMenuItemFromMenu() {
JMenuItem menuItem = sMenuItem.get();
Objects.requireNonNull(menuItem, "The menu item should still be available at this point");
sMenu.remove(menuItem);
}
}

View file

@ -0,0 +1,2 @@
modules=java.desktop

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 8322133
* @summary Make sure getParameterSpec returns std name for EC AlgorithmParameters
* @modules java.base/sun.security.util
*/
import java.security.AlgorithmParameters;
import java.security.KeyPairGenerator;
import java.security.spec.ECGenParameterSpec;
public class CurveGetParameterSpec {
public static void main(String[] args) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
kpg.initialize(new ECGenParameterSpec("secp384r1"));
var k = kpg.generateKeyPair().getPublic();
var a = AlgorithmParameters.getInstance("EC");
a.init(k.getParams());
String name = a.getParameterSpec(ECGenParameterSpec.class).getName();
if (!name.equals("secp384r1")) {
throw new Exception("EC getParameterSpec does not return std name secp384r1. Instead returns: " + name);
}
}
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2021, 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.
*
* 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.
*/
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.spec.MGF1ParameterSpec;
import java.util.Arrays;
/**
* @test
* @bug 8246797
* @summary Ensures OAEPParameters read correct encoding and
* reject encoding with invalid ordering
*/
public class OAEPOrder {
public static void main(String[] args) throws Exception {
// Do not use default fields
OAEPParameterSpec spec = new OAEPParameterSpec(
"SHA-384", "MGF1", MGF1ParameterSpec.SHA384,
new PSource.PSpecified(new byte[10]));
AlgorithmParameters alg = AlgorithmParameters.getInstance("OAEP");
alg.init(spec);
byte[] encoded = alg.getEncoded();
// Extract the fields inside encoding
// [0] HashAlgorithm
byte[] a0 = Arrays.copyOfRange(encoded, 2, encoded[3] + 4);
// [1] MaskGenAlgorithm + [2] PSourceAlgorithm
byte[] a12 = Arrays.copyOfRange(encoded, 2 + a0.length, encoded.length);
// and rearrange [1] and [2] before [0]
System.arraycopy(a12, 0, encoded, 2, a12.length);
System.arraycopy(a0, 0, encoded, 2 + a12.length, a0.length);
AlgorithmParameters alg2 = AlgorithmParameters.getInstance("OAEP");
try {
alg2.init(encoded);
throw new RuntimeException("Should fail");
} catch (IOException ioe) {
// expected
}
}
}

View file

@ -0,0 +1,116 @@
/*
* Copyright (c) 2007, 2015, 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.
*
* 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.
*/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Arrays;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
/*
* @test
* @bug 8048604
* @summary This test verifies the assertion "The chaining feature of
* Filter streams should be supported." for feature "CipherInputStream &
* CipherOutputStream"
* @run main CICOChainingTest
*/
public class CICOChainingTest {
/**
* Plain text length.
*/
private static final int PLAIN_TEXT_LENGTH = 200;
public static void main(String argv[]) throws Exception {
CICOChainingTest test = new CICOChainingTest();
test.chainTest(true);
test.chainTest(false);
}
/**
* Chain CipherInputStream/CipherOutputStream with other stream, encrypt
* the text and decrypt it, recovered text is supposed to be same as
* original text.
* @param useInt true if read byte by byte false if read with buffer.
* @throws IOException any I/O operation failed.
*/
public void chainTest(boolean useInt) throws IOException {
byte[] plainText = TestUtilities.generateBytes(PLAIN_TEXT_LENGTH);
byte[] recoveredText = new byte[plainText.length];
// Do initialization
try (MyNullCipherInputStream ciInput1 = new MyNullCipherInputStream(
new ByteArrayInputStream(plainText));
PipedOutputStream piOut = new PipedOutputStream();
MyNullCipherInputStream ciInput2 = new MyNullCipherInputStream(
new PipedInputStream(piOut));
MyNullCipherOutputStream ciOut = new MyNullCipherOutputStream(
piOut);) {
if (useInt) {
int buffer = ciInput1.read();
while (buffer != -1) {
piOut.write(buffer);
buffer = ciInput1.read();
}
} else {
byte[] buffer = new byte[20];
int len = ciInput1.read(buffer);
while (len != -1) {
ciOut.write(buffer, 0, len);
len = ciInput1.read(buffer);
}
}
ciOut.flush();
piOut.flush();
// Get the output
ciInput2.read(recoveredText);
if (ciInput2.available() > 0) {
throw new RuntimeException("Expected no data from ciInput2, but"
+ " ciInput2.available() = " + ciInput2.available());
}
}
// Verify output is same to input.
if (!Arrays.equals(plainText, recoveredText)) {
throw new RuntimeException("plainText:" + new String(plainText)
+ " recoveredText:" + new String(recoveredText)
+ " Test failed due to result compare fail");
}
}
}
class MyNullCipherInputStream extends CipherInputStream {
public MyNullCipherInputStream(InputStream is) {
super(is);
}
}
class MyNullCipherOutputStream extends CipherOutputStream {
public MyNullCipherOutputStream(OutputStream os) {
super(os);
}
}

View file

@ -0,0 +1,143 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import static java.lang.System.out;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
/*
* @test
* @bug 8048604
* @summary to verify cipherInputStream and cipherInputStream cipher function
* @run main CICODESFuncTest
*/
public class CICODESFuncTest {
/**
* Algorithms name.
*/
private static final String[] ALGORITHMS = { "DES", "DESede", "Blowfish" };
private static final String[] MODES = { "ECB", "CBC", "CFB", "CFB24",
"CFB32", "CFB40", "CFB72", "OFB", "OFB20", "OFB48", "OFB56",
"OFB64", "PCBC" };
/**
* Padding mode.
*/
private static final String[] PADDINGS = { "noPadding", "pkcs5padding" };
/**
* Plain text length.
*/
private static final int TEXT_LENGTH = 80;
/**
* Initialization vector length.
*/
private static final int IV_LENGTH = 8;
public static void main(String[] args) throws Exception {
Provider provider = Security.getProvider(
System.getProperty("test.provider.name", "SunJCE"));
if (provider == null) {
throw new RuntimeException("SunJCE provider does not exist.");
}
for (String algorithm : ALGORITHMS) {
for (String mode : MODES) {
// We only test noPadding and pkcs5padding for CFB72, OFB20, ECB
// PCBC and CBC. Otherwise test noPadding only.
int padKinds = 1;
if (mode.equalsIgnoreCase("CFB72")
|| mode.equalsIgnoreCase("OFB20")
|| mode.equalsIgnoreCase("ECB")
|| mode.equalsIgnoreCase("PCBC")
|| mode.equalsIgnoreCase("CBC")) {
padKinds = PADDINGS.length;
}
// PKCS5padding is meaningful only for ECB, CBC, PCBC
for (int k = 0; k < padKinds; k++) {
for (ReadModel readMode : ReadModel.values()) {
runTest(provider, algorithm, mode, PADDINGS[k], readMode);
}
}
}
}
}
private static void runTest(Provider p, String algo, String mo, String pad,
ReadModel whichRead) throws GeneralSecurityException, IOException {
// Do initialization
byte[] plainText = TestUtilities.generateBytes(TEXT_LENGTH);
byte[] iv = TestUtilities.generateBytes(IV_LENGTH);
AlgorithmParameterSpec aps = new IvParameterSpec(iv);
try {
KeyGenerator kg = KeyGenerator.getInstance(algo, p);
out.println(algo + "/" + mo + "/" + pad + "/" + whichRead);
SecretKey key = kg.generateKey();
Cipher ci1 = Cipher.getInstance(algo + "/" + mo + "/" + pad, p);
if ("CFB72".equalsIgnoreCase(mo) || "OFB20".equalsIgnoreCase(mo)) {
throw new RuntimeException(
"NoSuchAlgorithmException not throw when mode"
+ " is CFB72 or OFB20");
}
Cipher ci2 = Cipher.getInstance(algo + "/" + mo + "/" + pad, p);
if ("ECB".equalsIgnoreCase(mo)) {
ci1.init(Cipher.ENCRYPT_MODE, key);
ci2.init(Cipher.DECRYPT_MODE, key);
} else {
ci1.init(Cipher.ENCRYPT_MODE, key, aps);
ci2.init(Cipher.DECRYPT_MODE, key, aps);
}
ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
try (CipherInputStream cInput
= new CipherInputStream(
new ByteArrayInputStream(plainText), ci1);
CipherOutputStream ciOutput
= new CipherOutputStream(baOutput, ci2);) {
// Read from the input and write to the output using 2 types
// of buffering : byte[] and int
whichRead.read(cInput, ciOutput, ci1, plainText.length);
}
// Verify input and output are same.
if (!Arrays.equals(plainText, baOutput.toByteArray())) {
throw new RuntimeException("Test failed due to compare fail ");
}
} catch (NoSuchAlgorithmException nsaEx) {
if ("CFB72".equalsIgnoreCase(mo) || "OFB20".equalsIgnoreCase(mo)) {
out.println("NoSuchAlgorithmException is expected for CFB72 and OFB20");
} else {
throw new RuntimeException("Unexpected exception testing: "
+ algo + "/" + mo + "/" + pad + "/" + whichRead, nsaEx);
}
}
}
}

View file

@ -0,0 +1,271 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import static java.lang.System.out;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
/*
* @test
* @bug 8048604
* @summary This test verifies the assertion "The skip feature of Filter
* streams should be supported." for feature
* CipherInputStream and CipherOutputStream
*/
public class CICOSkipTest {
/**
* Block length.
*/
private static final int BLOCK = 50;
/**
* Saving bytes length.
*/
private static final int SAVE = 45;
/**
* Plain text length.
*/
private static final int PLAIN_TEXT_LENGTH = 800;
/**
* Skip reading byte size. This should be same to BLOCK - SAVE
*/
private static final int DISCARD = BLOCK - SAVE;
private static final String[] ALGOS = {"DES", "DESede", "Blowfish"};
private static final String[] MODES = {"ECB", "CBC", "CFB", "CFB32",
"OFB", "OFB64", "PCBC"};
private static final String[] PADDINGS = {"NoPadding", "Pkcs5Padding"};
private static final String[] PBE_ALGOS = {"PBEWithMD5AndDES",
"PBEWithMD5AndDES/CBC/PKCS5Padding", "PBEWithSHA1AndDESede"};
public static void main(String[] args) throws Exception {
// how many kinds of padding mode such as PKCS5padding and NoPadding
for (String algo : ALGOS) {
for (String mode : MODES) {
int padKinds = 1;
if (mode.equalsIgnoreCase("ECB")
|| mode.equalsIgnoreCase("PCBC")
|| mode.equalsIgnoreCase("CBC")) {
padKinds = PADDINGS.length;
}
// PKCS5padding is meaningful only for ECB, CBC, PCBC
for (int k = 0; k < padKinds; k++) {
String info = algo + "/" + mode + "/" + PADDINGS[k];
try {
CipherGenerator cg = new CipherGenerator(algo, mode,
PADDINGS[k]);
for (ReadMethod model : ReadMethod.values()) {
runTest(cg.getPair(), info, model);
}
} catch (LengthLimitException exp) {
// skip this if this key length is larger than what's
// configured in the jce jurisdiction policy files
out.println(exp.getMessage() + " is expected.");
}
}
}
}
for (String pbeAlgo : PBE_ALGOS) {
for (ReadMethod model : ReadMethod.values()) {
System.out.println("Testing Algorithm : " + pbeAlgo
+ " ReadMethod : " + model);
runTest(new CipherGenerator(pbeAlgo).getPair(), pbeAlgo, model);
}
}
}
private static void runTest(Cipher[] pair, String info, ReadMethod whichRead)
throws IOException {
byte[] plainText = TestUtilities.generateBytes(PLAIN_TEXT_LENGTH);
out.println("Testing: " + info + "/" + whichRead);
try (ByteArrayInputStream baInput = new ByteArrayInputStream(plainText);
CipherInputStream ciInput1 = new CipherInputStream(baInput,
pair[0]);
CipherInputStream ciInput2 = new CipherInputStream(ciInput1,
pair[1]);) {
// Skip 5 bytes after read 45 bytes and repeat until finish
// (Read from the input and write to the output using 2 types
// of buffering : byte[] and int)
// So output has size:
// (OVERALL/BLOCK)* SAVE = (800 / 50) * 45 = 720 bytes
int numOfBlocks = plainText.length / BLOCK;
// Output buffer.
byte[] outputText = new byte[numOfBlocks * SAVE];
int index = 0;
for (int i = 0; i < numOfBlocks; i++) {
index = whichRead.readByte(ciInput2, outputText, SAVE, index);
// If available is more than expected discard byte size. Skip
// discard bytes, otherwise try to read discard bytes by read.
if (ciInput2.available() >= DISCARD) {
ciInput2.skip(DISCARD);
} else {
for (int k = 0; k < DISCARD; k++) {
ciInput2.read();
}
}
}
// Verify output is same as input
if (!TestUtilities
.equalsBlockPartial(plainText, outputText, BLOCK, SAVE)) {
throw new RuntimeException("Test failed with compare fail");
}
}
}
}
class CipherGenerator {
/**
* Initialization vector length.
*/
private static final int IV_LENGTH = 8;
private static final String PASSWD = "Sesame!(@#$%^&*)";
private final Cipher[] pair = new Cipher[2];
// For DES/DESede ciphers
CipherGenerator(String algo, String mo, String pad)
throws NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException,
NoSuchPaddingException, SecurityException, LengthLimitException {
// Do initialization
KeyGenerator kg = KeyGenerator.getInstance(algo);
SecretKey key = kg.generateKey();
if (key.getEncoded().length * 8 > Cipher.getMaxAllowedKeyLength(algo)) {
// skip this if this key length is larger than what's
// configured in the jce jurisdiction policy files
throw new LengthLimitException(
"Skip this test if key length is larger than what's"
+ "configured in the jce jurisdiction policy files");
}
AlgorithmParameterSpec aps = null;
if (!mo.equalsIgnoreCase("ECB")) {
byte[] iv = TestUtilities.generateBytes(IV_LENGTH);
aps = new IvParameterSpec(iv);
}
initCiphers(algo + "/" + mo + "/" + pad, key, aps);
}
// For PBE ciphers
CipherGenerator(String algo) throws NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException,
NoSuchPaddingException, InvalidKeySpecException {
// Do initialization
byte[] salt = TestUtilities.generateBytes(IV_LENGTH);
int iterCnt = 6;
SecretKeyFactory skf = SecretKeyFactory.getInstance(algo.split("/")[0]);
SecretKey key = skf
.generateSecret(new PBEKeySpec(PASSWD.toCharArray()));
AlgorithmParameterSpec aps = new PBEParameterSpec(salt, iterCnt);
initCiphers(algo, key, aps);
}
private void initCiphers(String algo, SecretKey key,
AlgorithmParameterSpec aps) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException {
String providerName = System.getProperty("test.provider.name", "SunJCE");
Provider provider = Security.getProvider(providerName);
if (provider == null) {
throw new RuntimeException(providerName + " provider does not exist.");
}
Cipher ci1 = Cipher.getInstance(algo, provider);
ci1.init(Cipher.ENCRYPT_MODE, key, aps);
pair[0] = ci1;
Cipher ci2 = Cipher.getInstance(algo, provider);
ci2.init(Cipher.DECRYPT_MODE, key, aps);
pair[1] = ci2;
}
Cipher[] getPair() {
return pair;
}
}
enum ReadMethod {
// read one byte at a time for save times
READ_ONE_BYTE {
@Override
int readByte(CipherInputStream ciIn2, byte[] outputText, int save,
int index) throws IOException {
for (int j = 0; j < save; j++, index++) {
int buffer0 = ciIn2.read();
if (buffer0 != -1) {
outputText[index] = (byte) buffer0;
} else {
break;
}
}
return index;
}
},
// read a chunk of save bytes if possible
READ_BLOCK {
@Override
int readByte(CipherInputStream ciIn2, byte[] outputText, int save,
int index) throws IOException {
int len1 = ciIn2.read(outputText, index, save);
out.println("Init: index=" + index + ",len=" + len1);
// read more until save bytes
index += len1;
int len2 = 0;
while (len1 != save && len2 != -1) {
len2 = ciIn2.read(outputText, index, save - len1);
out.println("Cont: index=" + index + ",len=" + len2);
len1 += len2;
index += len2;
}
return index;
}
};
abstract int readByte(CipherInputStream ciIn2, byte[] outputText, int save,
int index) throws IOException;
};
class LengthLimitException extends Exception {
public LengthLimitException(String string) {
super(string);
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.Security;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
/**
* Wrapper class to test a given AES-based PBE algorithm.
*/
public class AESPBEWrapper extends AbstractPBEWrapper {
/**
* the algorithm parameters.
*/
private AlgorithmParameters pbeParams;
/**
* the encryption key.
*/
private final SecretKey key;
/**
* The Wrapper constructor. Instantiate Cipher using the given AES-based PBE
* algorithm.
*
* @param algo AES-based PBE algorithm.
* @param passwd password phrase.
* @throws GeneralSecurityException all security exceptions are thrown.
*/
public AESPBEWrapper(PBEAlgorithm algo, String passwd)
throws GeneralSecurityException {
// salt and iteration count will be generated during encryption
super(algo, passwd, 0);
// Generate secret key. We expect no mode and padding specified.
SecretKeyFactory skf = SecretKeyFactory.getInstance(algo.baseAlgo);
key = skf.generateSecret(new PBEKeySpec(passwd.toCharArray()));
}
/**
* Initiate the Cipher object using given "mode".
* @return a cipher object.
* @throws GeneralSecurityException all security exceptions are thrown.
*/
@Override
protected Cipher initCipher(int mode) throws GeneralSecurityException {
String providerName = System.getProperty("test.provider.name", "SunJCE");
Provider provider = Security.getProvider(providerName);
if (provider == null) {
throw new RuntimeException(providerName + ": provider does not exist.");
}
// get Cipher instance
Cipher ci = Cipher.getInstance(transformation, provider);
if (Cipher.ENCRYPT_MODE == mode) {
ci.init(Cipher.ENCRYPT_MODE, key);
pbeParams = ci.getParameters();
} else {
ci.init(Cipher.DECRYPT_MODE, key, pbeParams);
}
return ci;
}
}

View file

@ -0,0 +1,103 @@
/*
* Copyright (c) 2007, 2025, 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.
*
* 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.
*/
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
/**
* PBEWrapper is an abstract class for all concrete PBE Cipher wrappers.
*/
public abstract class AbstractPBEWrapper {
/**
* Iteration count.
*/
public static final int DEFAULT_ITERATION = 1000;
public static final String PBKDF2 = "PBKDF2";
public static final String AES = "AES";
public static final String DEFAULT = "default";
/**
* transformation the name of the transformation, e.g.,
* DES/CBC/PKCS5Padding
*/
protected final String transformation;
/**
* the standard name of the requested secret key algorithm.
*/
protected final String baseAlgo;
/**
* The contents of salt are copied to protect against subsequent
* modification.
*/
protected final byte[] salt;
/**
* Password.
*/
protected final String password;
/**
* PBEWrapper creator.
*
* @param algo PBE algorithm to test
* @param passwd a password phrase
* @return PBEWrapper in accordance to requested algo.
* @throws GeneralSecurityException all exceptions are thrown.
*/
public static AbstractPBEWrapper createWrapper(PBEAlgorithm algo, String passwd)
throws GeneralSecurityException {
switch (algo.type) {
case PBKDF2:
return new PBKDF2Wrapper(algo, passwd);
case AES:
return new AESPBEWrapper(algo, passwd);
default:
return new DefaultPBEWrapper(algo, passwd);
}
}
/**
* PBEWrapper constructor.
*
* @param algo algorithm to wrap
* @param password password phrase
* @param saltSize salt size (defined in subclasses)
*/
protected AbstractPBEWrapper(PBEAlgorithm algo, String password, int saltSize) {
this.transformation = algo.getTransformation();
this.baseAlgo = algo.baseAlgo;
this.salt = TestUtilities.generateBytes(saltSize);
this.password = password;
}
/**
* Initialize Cipher object for the operation requested in the mode parameter.
*
* @param mode encryption or decryption
* @return a cipher initialize by mode.
* @throws GeneralSecurityException all security exceptions are thrown.
*/
protected abstract Cipher initCipher(int mode) throws GeneralSecurityException;
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2007, 2015, 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.
*
* 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.
*/
/*
* @test
* @bug 8048604
* @summary This test verifies the assertion "The encrypt/decrypt
* mechanism of cipher should perform correctly." for feature
* "CipherInputStream & CipherOutputStream".
* @library ../
* @run main CICOPBEFuncTest
*/
import java.util.Arrays;
import javax.crypto.Cipher;
public class CICOPBEFuncTest {
public static void main(String[] args) throws Exception {
for (PBEAlgorithm algorithm : PBEAlgorithm.values()) {
// int buffertin test
String algo = algorithm.baseAlgo.toUpperCase();
if (!algo.contains("TRIPLEDES") && !algo.contains("AES_256")
|| Cipher.getMaxAllowedKeyLength(algo) > 128) {
// skip this if this key length is larger than what's
// configured in the jce jurisdiction policy files
System.out.println("Testing " + algorithm.getTransformation());
for (String type : Arrays.asList(CICO_PBE_Test.INT_BYTE_BUFFER,
CICO_PBE_Test.BYTE_ARR_BUFFER)) {
new CICO_PBE_RW_Test(algorithm)
.proceedTest(type);
new CICO_PBE_SKIP_Test(algorithm)
.proceedTest(type);
}
}
}
}
}

View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2007, 2015, 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.
*
* 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.
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import javax.crypto.CipherOutputStream;
/**
* CICO PBE Read/Write functional test.
*
* Verifies for the given PBE algorithm if the encrypt/decrypt mechanism is
* performed correctly for CipherInputStream and CipherOutputStream.
*
* Test scenario:
* 1. initializes plain text with random generated data.
* 2. for the given PBE algorithm instantiates encrypt and decrypt Ciphers.
* 3. instantiates CipherInputStream with the encrypt Cipher.
* 4. instantiates CipherOutputStream with the decrypt Cipher.
* 5. performs reading from the CipherInputStream (encryption data) and writing
* to the CipherOutputStream (decryption). As a result the output of the
* CipherOutputStream should be the same as an original plain text.
* 6. compares if the original plain text is the same as the output of the
* CipherOutputStream.
*
* The test implements 2 test cases in accordance with buffering type:
* 1. byte array buffering
* 2. int buffering
*/
public class CICO_PBE_RW_Test extends CICO_PBE_Test {
public CICO_PBE_RW_Test(PBEAlgorithm pbeAlgo)
throws GeneralSecurityException {
super(pbeAlgo);
}
/**
* The CICO PBE RW test specific part of the super.doTest(). Implements the
* scenario in accordance to the class description.
* @param type byteArrayBuffering or intByteBuffering
* @throws IOException any I/O operation failed.
* @throws GeneralSecurityException any security error.
*/
@Override
public void proceedTest(String type) throws IOException,
GeneralSecurityException {
ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
try (CipherOutputStream ciOutput = new CipherOutputStream(baOutput,
getDecryptCipher())) {
if (type.equals(CICO_PBE_Test.BYTE_ARR_BUFFER)) {
proceedTestUsingByteArrayBuffer(ciOutput);
} else {
proceedTestUsingIntBuffer(ciOutput);
}
ciOutput.flush();
}
// Compare input and output
if (!TestUtilities.equalsBlock(plainText, baOutput.toByteArray(), TEXT_SIZE)) {
throw new RuntimeException("outputText not same with expectedText"
+ " when test " + type);
}
}
/**
* Implements byte array buffering type test case of the CICO PBE RW test.
* @param ciOutput output stream for data written.
* @throws java.io.IOException any I/O operation failed.
*/
public void proceedTestUsingByteArrayBuffer(
CipherOutputStream ciOutput) throws IOException {
byte[] buffer = new byte[TEXT_SIZE];
int len = getCiInput().read(buffer);
while (len != -1) {
ciOutput.write(buffer, 0, len);
len = getCiInput().read(buffer);
}
}
/**
* Implements int buffering type test case.
* @param ciOutput output stream for data written.
* @throws java.io.IOException any I/O operation failed.
*/
public void proceedTestUsingIntBuffer(CipherOutputStream ciOutput)
throws IOException {
int buffer = getCiInput().read();
while (buffer != -1) {
ciOutput.write(buffer);
buffer = getCiInput().read();
}
}
}

View file

@ -0,0 +1,168 @@
/*
* Copyright (c) 2007, 2015, 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.
*
* 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.
*/
import java.io.IOException;
import java.security.GeneralSecurityException;
import javax.crypto.CipherInputStream;
/**
* CICO PBE SKIP functional test.
*
* Verifies for the given PBE algorithm if the encrypt/decrypt mechanism is
* performed correctly for CipherInputStream when skip() method is used.
*
* Test scenario:
* 1. initializes plain text with random generated data with length TEXT_SIZE.
* 2. for the given PBE algorithm instantiates encrypt and decrypt Ciphers.
* 3. instantiates CipherInputStream 1 with the encrypt Cipher.
* 4. instantiates CipherInputStream 2 with the CipherInputStream 1 and decrypt
* Cipher.
* 5. the plain text is divided on TEXT_SIZE/BLOCK blocks. Reading from
* CipherInputStream 2 one block at time. The last BLOCK - SAVE bytes are
* skipping for each block. Therefor the plain text data go through
* CipherInputStream 1 (encrypting) and CipherInputStream 2 (decrypting).
* As a result the output should equal to the original text except DISCARD
* byte for each block are skipped.
* 6. get the standard output.
* 7. compares the expected standard output with the output of the
* CipherInputStream 2. If it is the same the test passed. Otherwise it
* failed. Any uncaught exceptions should be considered as an error.
* The test implements 2 test cases in accordance with a buffering type:
* 1. byte array buffering
* 2. int buffering
*/
public class CICO_PBE_SKIP_Test extends CICO_PBE_Test {
/**
* Block size.
*/
private static final int BLOCK = 50;
/**
* Valid reading byte size.
*/
private static final int SAVE = 45;
/**
* Skip reading byte size. This should be same to BLOCK - SAVE
*/
private static final int DISCARD = BLOCK - SAVE;
/**
* Number of blocks.
*/
private static final int NUMBER_OF_BLOCKS = TEXT_SIZE / BLOCK;
private final byte[] outputText;
/**
* CICO PBE Skip test constructor
*
* @param pbeAlgo the PBE algorithm to test.
* @throws java.security.GeneralSecurityException
*/
public CICO_PBE_SKIP_Test(PBEAlgorithm pbeAlgo)
throws GeneralSecurityException {
super(pbeAlgo);
outputText = new byte[NUMBER_OF_BLOCKS * SAVE];
}
/**
* Implements byte array buffering type test case of the CICO SKIP test.
*
* @param blockNum block number to read.
*/
private void proceedSkipTestUsingByteArrayBufferingType(
CipherInputStream ciIn2, int blockNum) throws IOException {
int index = blockNum * SAVE;
int len1 = ciIn2.read(outputText, index, SAVE);
// read more until SAVE bytes
index += len1;
int len2 = 0;
int totalRead = len1;
while (len1 != SAVE && len2 != -1) {
len2 = ciIn2.read(outputText, index, SAVE - len1);
len1 += len2;
index += len2;
totalRead += len2;
}
if (totalRead != SAVE) {
throw new RuntimeException("Read bytes number " + totalRead
+ " does not equal to given number " + SAVE);
}
}
/**
* Implements int buffering type test case of the CICO SKIP test.
*
* @param blockNum block number to read.
*/
private void proceedSkipTestUsingIntBufferingType(CipherInputStream ciIn2,
int blockNum) throws IOException {
int index = blockNum * SAVE;
int totalRead = 0;
for (int j = 0; j < SAVE; j++, index++) {
int buffer0 = ciIn2.read();
if (buffer0 != -1) {
outputText[index] = (byte) buffer0;
totalRead++;
} else {
break;
}
}
if (totalRead != SAVE) {
throw new RuntimeException("Read bytes number " + totalRead
+ " does not equal to given number " + SAVE);
}
}
/**
* The CICO PBE SKIP test specific part of the super.doTest(). Implements
* the scenario in accordance to the class description.
* @throws java.io.IOException any I/O failed.
*/
@Override
public void proceedTest(String type) throws IOException {
System.out.println("Test type: " + type);
// init second input stream with decrypt Cipher
try (CipherInputStream ciIn2 = new CipherInputStream(getCiInput(),
getDecryptCipher())) {
for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
if (type.equals(CICO_PBE_Test.BYTE_ARR_BUFFER)) {
proceedSkipTestUsingByteArrayBufferingType(ciIn2, i);
} else {
proceedSkipTestUsingIntBufferingType(ciIn2, i);
}
if (ciIn2.available() >= DISCARD) {
ciIn2.skip(DISCARD);
} else {
for (int k = 0; k < DISCARD; k++) {
ciIn2.read();
}
}
}
}
if (!TestUtilities.equalsBlockPartial(plainText, outputText, BLOCK, SAVE)) {
throw new RuntimeException("outputText not same with expectedText"
+ " when test " + type);
}
}
}

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2007, 2015, 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.
*
* 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.
*/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
/**
* This is an abstract class for CipherInputStream/CipherOutputStream PBE
* functional tests.
*/
public abstract class CICO_PBE_Test {
/**
* Sample string for byte buffer.
*/
public static final String BYTE_ARR_BUFFER = "byteArrayBuffering";
/**
* Sample string for int buffer.
*/
public static final String INT_BYTE_BUFFER = "intByteBuffering";
public static final String PASS_PHRASE = "Some password phrase!";
/**
* Text string size.
*/
public static final int TEXT_SIZE = 800;
protected final byte[] plainText;
private final Cipher encryptCipher, decryptCipher;
/**
* An CipherInputStream for reading cipher and plain text.
*/
private final CipherInputStream ciInput;
/**
* Constructor by algorithm.
* @param pbeAlgo PBE algorithm to test.
* @throws GeneralSecurityException if any security error.
*/
public CICO_PBE_Test(PBEAlgorithm pbeAlgo) throws GeneralSecurityException {
// Do initialization of the plainText
plainText = TestUtilities.generateBytes(TEXT_SIZE);
// Do initialization of the ciphers
AbstractPBEWrapper pbeWrap = AbstractPBEWrapper.createWrapper(pbeAlgo, PASS_PHRASE);
encryptCipher = pbeWrap.initCipher(Cipher.ENCRYPT_MODE);
decryptCipher = pbeWrap.initCipher(Cipher.DECRYPT_MODE);
// init cipher input stream
ciInput = new CipherInputStream(new ByteArrayInputStream(plainText),
encryptCipher);
}
protected byte[] getPlainText() {
return plainText;
}
/**
* The body of the test. Should be defined in subclasses.
* @param type byteArrayBuffering or intByteBuffering
* @throws IOException I/O operation failed.
* @throws GeneralSecurityException all exceptions thrown.
*/
protected abstract void proceedTest(String type)
throws IOException, GeneralSecurityException;
protected Cipher getEncryptCipher() {
return encryptCipher;
}
public CipherInputStream getCiInput() {
return ciInput;
}
public Cipher getDecryptCipher() {
return decryptCipher;
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2001, 2017, 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.
*
* 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.
*/
/*
* @test
* @bug 8048604
* @library ../ /test/lib
* @build jdk.test.lib.RandomFactory
* @run main CipherNCFuncTest
* @summary This test verifies the assertion "There should be no transformation
* on the plaintext/ciphertext in encryption/decryption mechanism" for
* feature "NullCipher".
*/
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NullCipher;
import javax.crypto.ShortBufferException;
import jdk.test.lib.RandomFactory;
public class CipherNCFuncTest {
public static void main(String[] args) throws ShortBufferException,
IllegalBlockSizeException, BadPaddingException {
byte[] plainText = new byte[801];
// Initialization
RandomFactory.getRandom().nextBytes(plainText);
Cipher ci = new NullCipher();
// Encryption
byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
int offset = ci.update(plainText, 0, plainText.length, cipherText, 0);
ci.doFinal(cipherText, offset);
// Decryption
byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
int len = ci.doFinal(cipherText, 0, cipherText.length, recoveredText);
// Comparison
if (len != plainText.length ||
!TestUtilities.equalsBlock(plainText, cipherText, len) ||
!TestUtilities.equalsBlock(plainText, recoveredText, len)) {
throw new RuntimeException(
"Test failed because plainText not equal to cipherText and revoveredText");
}
}
}

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.Security;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
/**
* Default wrapper for a password based encryption Cipher.
*/
public class DefaultPBEWrapper extends AbstractPBEWrapper {
/**
* Define default SALT size as 8.
*/
private static final int PBE_SALT_SIZE = 8;
/**
* Default PBE wrapper constructor.
*
* @param algo PGE algorithm to wrap.
* @param passwd password phrase
*/
public DefaultPBEWrapper(PBEAlgorithm algo, String passwd) {
super(algo, passwd, PBE_SALT_SIZE);
}
/**
* Instantiate Cipher for the PBE algorithm.
*
* @param mode Cipher mode: encrypt or decrypt.
* @return Cipher in accordance to the PBE algorithm
* @throws java.security.GeneralSecurityException
*/
@Override
protected Cipher initCipher(int mode) throws GeneralSecurityException {
String providerName = System.getProperty("test.provider.name", "SunJCE");
Provider provider = Security.getProvider(providerName);
if (provider == null) {
throw new RuntimeException(providerName + ": provider does not exist.");
}
SecretKey key = SecretKeyFactory.getInstance(baseAlgo)
.generateSecret(new PBEKeySpec(password.toCharArray()));
Cipher ci = Cipher.getInstance(transformation, provider);
ci.init(mode, key, new PBEParameterSpec(salt, DEFAULT_ITERATION));
return ci;
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2007, 2022, 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.
*
* 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.
*/
import java.util.StringJoiner;
public enum PBEAlgorithm {
MD5_DES("PBEWithMD5ANDdes", "", "", AbstractPBEWrapper.DEFAULT),
MD5_DES_CBC_PKCS5("PBEWithMD5AndDES", "CBC", "PKCS5Padding",
AbstractPBEWrapper.DEFAULT),
MD5_TRIPLEDES("PBEWithMD5ANDtripledes", "", "", AbstractPBEWrapper.DEFAULT),
MD5_TRIPLEDES_CBC_PKCS5("PBEWithMD5AndTRIPLEDES", "CBC", "PKCS5Padding",
AbstractPBEWrapper.DEFAULT),
SHA1_DESEDE("PBEwithSHA1AndDESede", "", "", AbstractPBEWrapper.DEFAULT),
SHA1_DESEDE_CBC_PKCS5("PBEwithSHA1AndDESede", "CBC", "PKCS5Padding",
AbstractPBEWrapper.DEFAULT),
SHA1_RC2_40("PBEwithSHA1AndRC2_40", "", "", AbstractPBEWrapper.DEFAULT),
SHA1_RC2_40_PKCS5("PBEwithSHA1Andrc2_40", "CBC", "PKCS5Padding",
AbstractPBEWrapper.DEFAULT),
SHA1_RC2_128("PBEWithSHA1AndRC2_128", "", "", AbstractPBEWrapper.DEFAULT),
SHA1_RC2_128_PKCS5("PBEWithSHA1andRC2_128", "CBC", "PKCS5Padding",
AbstractPBEWrapper.DEFAULT),
SHA1_RC4_40("PBEWithSHA1AndRC4_40", "", "", AbstractPBEWrapper.DEFAULT),
SHA1_RC4_40_ECB_NOPADDING("PBEWithsha1AndRC4_40", "ECB", "NoPadding",
AbstractPBEWrapper.DEFAULT),
SHA1_RC4_128("PBEWithSHA1AndRC4_128", "", "", AbstractPBEWrapper.DEFAULT),
SHA1_RC4_128_ECB_NOPADDING("pbeWithSHA1AndRC4_128", "ECB", "NoPadding",
AbstractPBEWrapper.DEFAULT),
HMAC_SHA1_AES_128("PBEWithHmacSHA1AndAES_128", "", "", AbstractPBEWrapper.AES),
HMAC_SHA224_AES_128("PBEWithHmacSHA224AndAES_128", "", "", AbstractPBEWrapper.AES),
HMAC_SHA256_AES_128("PBEWithHmacSHA256AndAES_128", "", "", AbstractPBEWrapper.AES),
HMAC_SHA384_AES_128("PBEWithHmacSHA384AndAES_128", "", "", AbstractPBEWrapper.AES),
HMAC_SHA512_AES_128("PBEWithHmacSHA512AndAES_128", "", "", AbstractPBEWrapper.AES),
HMAC_SHA512_224_AES_128("PBEWithHmacSHA512/224AndAES_128", "", "", AbstractPBEWrapper.AES),
HMAC_SHA512_256_AES_128("PBEWithHmacSHA512/256AndAES_128", "", "", AbstractPBEWrapper.AES),
HMAC_SHA1_AES_256("PBEWithHmacSHA1AndAES_256", "", "", AbstractPBEWrapper.AES),
HMAC_SHA224_AES_256("PBEWithHmacSHA224AndAES_256", "", "", AbstractPBEWrapper.AES),
HMAC_SHA256_AES_256("PBEWithHmacSHA256AndAES_256", "", "", AbstractPBEWrapper.AES),
HMAC_SHA384_AES_256("PBEWithHmacSHA384AndAES_256", "", "", AbstractPBEWrapper.AES),
HMAC_SHA512_AES_256("PBEWithHmacSHA512AndAES_256", "", "", AbstractPBEWrapper.AES),
HMAC_SHA512_224_AES_256("PBEWithHmacSHA512/224AndAES_256", "", "", AbstractPBEWrapper.AES),
HMAC_SHA512_256_AES_256("PBEWithHmacSHA512/256AndAES_256", "", "", AbstractPBEWrapper.AES),
PBKDF_HMAC_SHA1("PBKDF2WithHmacSHA1", "", "", AbstractPBEWrapper.PBKDF2),
PBKDF_HMAC_SHA224("PBKDF2WithHmacSHA224", "", "", AbstractPBEWrapper.PBKDF2),
PBKDF_HMAC_SHA256("PBKDF2WithHmacSHA256", "", "", AbstractPBEWrapper.PBKDF2),
PBKDF_HMAC_SHA384("PBKDF2WithHmacSHA384", "", "", AbstractPBEWrapper.PBKDF2),
PBKDF_HMAC_SHA512("PBKDF2WithHmacSHA512", "", "", AbstractPBEWrapper.PBKDF2),
PBKDF_HMAC_SHA512_224("PBKDF2WithHmacSHA512/224", "", "", AbstractPBEWrapper.PBKDF2),
PBKDF_HMAC_SHA512_256("PBKDF2WithHmacSHA512/256", "", "", AbstractPBEWrapper.PBKDF2);
final String baseAlgo;
final String mode;
final String padding;
final String type;
PBEAlgorithm(String alg, String mode, String padding, String type) {
this.baseAlgo = alg;
this.mode = mode;
this.padding = padding;
this.type = type;
}
public String getTransformation() {
StringJoiner sj = new StringJoiner("/");
sj.add(baseAlgo);
if (!mode.equals("")) {
sj.add(this.mode);
}
if (!padding.equals("")) {
sj.add(this.padding);
}
return sj.toString();
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.security.GeneralSecurityException;
import java.security.Provider;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
/**
* Wrapper class to test a given SecretKeyFactory.PBKDF2 algorithm.
*/
public class PBKDF2Wrapper extends AbstractPBEWrapper {
/**
* Default salt size.
*/
public static final int PBKDF2_SALT_SIZE = 64;
/**
* Default key length.
*/
public static final int PKDF2_DEFAULT_KEY_LEN = 128;
/**
* Default transformation.
*/
public static final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
/**
* Algorithm name.
*/
public static final String KEY_ALGORITHM = "AES";
/**
* Initialization vector length.
*/
private static final int IV_LENGTH = 16;
/**
* The buffer with the IV.
*/
private final byte[] iv;
/**
* PBKDF2Wrapper constructor. Instantiate Cipher using
* "AES/CBC/PKCS5Padding" transformation. Generate a secret key using PKDF2
* algorithms given in the "algo" parameter.
*
* @param algo AES-based PBE algorithm.
* @param passwd password phrase.
* @throws GeneralSecurityException all security exceptions are thrown.
*/
public PBKDF2Wrapper(PBEAlgorithm algo, String passwd)
throws GeneralSecurityException {
super(algo, passwd, PBKDF2_SALT_SIZE);
iv = TestUtilities.generateBytes(IV_LENGTH);
}
/**
* Initiate the Cipher object for PBKDF2 algorithm using given "mode".
*
* @param mode Cipher mode: encrypt or decrypt
* @return Cipher object for PBKDF2 algorithm
* @throws GeneralSecurityException all security exceptions are thrown.
*/
@Override
protected Cipher initCipher(int mode) throws GeneralSecurityException {
String providerName = System.getProperty("test.provider.name", "SunJCE");
Provider provider = Security.getProvider(providerName);
if (provider == null) {
throw new RuntimeException(providerName + ": provider does not exist.");
}
// Generate secret key
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(),
salt, DEFAULT_ITERATION, PKDF2_DEFAULT_KEY_LEN);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(baseAlgo);
SecretKey key = keyFactory.generateSecret(pbeKeySpec);
// get Cipher instance
Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION, provider);
cipher.init(mode,
new SecretKeySpec(key.getEncoded(),KEY_ALGORITHM),
new IvParameterSpec(iv));
return cipher;
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2007, 2015, 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.
*
* 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.
*/
import java.io.IOException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
/**
* ReadModel provides different way to test
* CipherInputStream.read()/read(byte[])/read(byte[], int, int) and
* CipherOutputStream.write(int)/write(byte[], int, int)/read(byte[]) API
*/
enum ReadModel {
READ_BYTE {
@Override
public void read(CipherInputStream cInput, CipherOutputStream ciOutput,
Cipher ciIn, int inputLen) throws IOException {
int buffer0 = cInput.read();
while (buffer0 != -1) {
ciOutput.write(buffer0);
buffer0 = cInput.read();
}
}
},
READ_BUFFER {
@Override
public void read(CipherInputStream cInput, CipherOutputStream ciOutput,
Cipher ciIn, int inputLen) throws IOException {
byte[] buffer1 = new byte[20];
int len1;
while ((len1 = cInput.read(buffer1)) != -1) {
ciOutput.write(buffer1, 0, len1);
}
}
},
READ_BUFFER_OFFSET {
@Override
public void read(CipherInputStream cInput, CipherOutputStream ciOutput,
Cipher ciIn, int inputLen) throws IOException {
byte[] buffer2 = new byte[ciIn.getOutputSize(inputLen)];
int offset2 = 0;
int len2 = 0;
while (len2 != -1) {
len2 = cInput.read(buffer2, offset2, buffer2.length - offset2);
offset2 += len2;
}
ciOutput.write(buffer2);
}
};
abstract public void read(CipherInputStream cInput,
CipherOutputStream ciOutput, Cipher ciIn, int inputLen)
throws IOException;
}

View file

@ -0,0 +1,90 @@
/*
* Copyright (c) 2007, 2015, 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.
*
* 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.
*/
/*
* utility class
*/
public class TestUtilities {
public static boolean equalsBlock(byte[] b1, byte[] b2, int len) {
for (int i = 0; i < len; i++) {
if (b1[i] != b2[i]) {
System.err.println("b1[" + i + "] : " + b1[i]
+ " b2[" + i + "] : " + b2[i]);
return false;
}
}
return true;
}
public static boolean equals(byte[] b1, byte[] b2) {
if (b2.length != b1.length) {
System.err.println("b1.length = " + b1.length
+ " b2.length = " + b2.length );
return false;
}
return equalsBlock(b1, b2, b1.length);
}
/**
* Verify b1's partial part is same as b2. compares b1 and b2 by chopping up
* b1 into blocks of b1BKSize and b2 into blocks of b2BKSize, and then
* compare the first b2BKSize bytes of each block, return true if they equal
* , otherwise return false.
* @param b1 byte array to be compared.
* @param b2 saved byte array.
* @param b1BKSize b1's block size.
* @param b2BKSize b2's block size.
* @return true is same. false otherwise.
*/
public static boolean equalsBlockPartial(byte[] b1, byte[] b2, int b1BKSize,
int b2BKSize) {
int numOfBlock = b1.length / b1BKSize;
for (int b = 0; b < numOfBlock; b++) {
for (int i = 0; i < b2BKSize; i++) {
int j1 = b * b1BKSize + i;
int j2 = b * b2BKSize + i;
if (b1[j1] != b2[j2]) {
System.err.println("Compare failed at b1[" + j1 + "]:" +
b1[j1] + " b2[" + j2 + "]:" + b2[j2]);
return false;
}
}
}
return true;
}
/**
* Generate a byte block by given length. The content of byte block
* is determined by the index.
* @param length length of byte array
* @return a byte array
*/
public static byte[] generateBytes(int length) {
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++) {
bytes[i] = (byte) (i & 0xff);
}
return bytes;
}
}

View file

@ -0,0 +1,970 @@
/*
* Copyright (c) 2020, 2024, 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.
*
* 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.
*/
/*
* @test
* @summary Use Cipher update and doFinal with a mixture of byte[], bytebuffer,
* and offset while verifying return values. Also using different and
* in-place buffers.
*
* in-place is not tested with different buffer types as it is not a logical
* scenario and is complicated by getOutputSize calculations.
*/
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HexFormat;
import java.util.List;
public class AEADBufferTest implements Cloneable {
// Data type for the operation
enum dtype { BYTE, HEAP, DIRECT };
// Data map
static HashMap<String, List<Data>> datamap = new HashMap<>();
// List of enum values for order of operation
List<dtype> ops;
static final String AES = "AES";
// The remaining input data length is inserted at the particular index
// in sizes[] during execution.
static final int REMAINDER = -1;
String algo;
boolean same = true;
int[] sizes;
boolean incremental = false;
// In some cases the theoretical check is too complicated to verify
boolean theoreticalCheck;
List<Data> dataSet;
int inOfs = 0, outOfs = 0;
static HexFormat hex = HexFormat.of();
static class Data {
int id;
SecretKey key;
byte[] iv;
int counter; // for CC20
byte[] pt;
byte[] aad;
byte[] ct;
byte[] tag;
int blockSize; // 16 for GCM, 0 for CC20
Data(String keyalgo, int id, String key, String iv, byte[] pt, String aad,
String ct, String tag) {
this(keyalgo, id, key, iv, 0,pt, aad, ct,tag);
}
Data(String keyalgo, int id, String key, String iv, String pt, String aad,
String ct, String tag) {
this(keyalgo, id, key, iv, HexToBytes(pt), aad, ct, tag);
}
Data(String keyalgo, int id, String key, String iv, int counter, byte[] pt, String aad,
String ct, String tag) {
this.id = id;
this.key = new SecretKeySpec(HexToBytes(key), keyalgo);
this.iv = HexToBytes(iv);
this.counter = counter;
this.pt = pt;
this.aad = HexToBytes(aad);
this.ct = HexToBytes(ct);
this.tag = HexToBytes(tag);
this.blockSize = (keyalgo.equals(AES) ? 16 : 0);
}
Data(String keyalgo, int id, String key, String iv, int counter, String pt, String aad,
String ct, String tag) {
this(keyalgo, id, key, iv, counter, HexToBytes(pt), aad, ct, tag);
}
Data(String keyalgo, int id, String key, int ivLen, int ptlen) {
this.id = id;
this.key = new SecretKeySpec(HexToBytes(key), keyalgo);
iv = new byte[ivLen];
counter = 0;
pt = new byte[ptlen];
tag = new byte[16];
aad = new byte[0];
boolean isGCM = keyalgo.equals(AES);
this.blockSize = (isGCM ? 16 : 0);
byte[] tct = null;
try {
SecureRandom r = new SecureRandom();
r.nextBytes(iv);
r.nextBytes(pt);
Cipher c = Cipher.getInstance(isGCM ? "AES/GCM/NoPadding": "ChaCha20-Poly1305");
c.init(Cipher.ENCRYPT_MODE, this.key,
getAPS(keyalgo, tag.length, iv));
tct = c.doFinal(pt);
} catch (Exception e) {
throw new RuntimeException("Error in generating data for length " +
ptlen, e);
}
ct = new byte[ptlen];
System.arraycopy(tct, 0, ct, 0, ct.length);
System.arraycopy(tct, ct.length, tag, 0, tag.length);
}
private static byte[] HexToBytes(String hexVal) {
if (hexVal == null) {
return new byte[0];
}
return hex.parseHex(hexVal);
}
}
/**
* Construct a test with an algorithm and a list of dtype.
* @param algo Algorithm string
* @param ops List of dtypes. If only one dtype is specified, only a
* doFinal operation will occur. If multiple dtypes are
* specified, the last is a doFinal, the others are updates.
*/
AEADBufferTest(String algo, List<dtype> ops) {
this.algo = algo;
this.ops = ops;
theoreticalCheck = true;
dataSet = datamap.get(algo);
}
public AEADBufferTest clone() throws CloneNotSupportedException{
return (AEADBufferTest)super.clone();
}
/**
* Define particular data sizes to be tested. "REMAINDER", which has a
* value of -1, can be used to insert the remaining input text length at
* that index during execution.
* @param sizes Data sizes for each dtype in the list.
*/
AEADBufferTest dataSegments(int[] sizes) {
this.sizes = sizes;
return this;
}
/**
* Do not perform in-place operations
*/
AEADBufferTest differentBufferOnly() {
this.same = false;
return this;
}
/**
* Enable incrementing through each data size available. This can only be
* used when the List has more than one dtype entry.
*/
AEADBufferTest incrementalSegments() {
this.incremental = true;
return this;
}
/**
* Specify a particular test dataset.
*
* @param id id value for the test data to used in this test.
*/
AEADBufferTest dataSet(int id) throws Exception {
for (Data d : datamap.get(algo)) {
if (d.id == id) {
dataSet = List.of(d);
return this;
}
}
throw new Exception("Unable to find dataSet id = " + id);
}
/**
* Set both input and output offsets to the same offset
* @param offset value for inOfs and outOfs
* @return
*/
AEADBufferTest offset(int offset) {
this.inOfs = offset;
this.outOfs = offset;
return this;
}
/**
* Set the input offset
* @param offset value for input offset
*/
AEADBufferTest inOfs(int offset) {
this.inOfs = offset;
return this;
}
/**
* Set the output offset
* @param offset value for output offset
*/
AEADBufferTest outOfs(int offset) {
this.outOfs = offset;
return this;
}
/**
* Reverse recursive loop that starts at the end-1 index, going to 0, in
* the size array to calculate all the possible sizes.
* It returns the remaining data size not used in the loop. This remainder
* is used for the end index which is the doFinal op.
*/
int inc(int index, int max, int total) {
if (sizes[index] == max - total) {
sizes[index + 1]++;
total++;
sizes[index] = 0;
} else if (index == 0) {
sizes[index]++;
}
total += sizes[index];
if (index > 0) {
return inc(index - 1, max, total);
}
return total;
}
// Call recursive loop and take returned remainder value for last index
boolean incrementSizes(int max) {
sizes[ops.size() - 1] = max - inc(ops.size() - 2, max, 0);
if (sizes[ops.size() - 2] == max) {
// We are at the end, exit test loop
return false;
}
return true;
}
void test() throws Exception {
int i = 1;
System.err.println("Algo: " + algo + " \tOps: " + ops.toString());
for (Data data : dataSet) {
// If incrementalSegments is enabled, run through that test only
if (incremental) {
if (ops.size() < 2) {
throw new Exception("To do incrementalSegments you must " +
"have more that 1 dtype in the list");
}
sizes = new int[ops.size()];
while (incrementSizes(data.pt.length)) {
System.err.print("Encrypt: Data Index: " + i + " \tSizes[ ");
for (int v : sizes) {
System.err.print(v + " ");
}
System.err.println("]");
encrypt(data);
}
Arrays.fill(sizes, 0);
while (incrementSizes(data.ct.length + data.tag.length)) {
System.err.print("Decrypt: Data Index: " + i + " \tSizes[ ");
for (int v : sizes) {
System.err.print(v + " ");
}
System.err.println("]");
decrypt(data);
}
} else {
// Default test of 0 and 2 offset doing in place and different
// i/o buffers
System.err.println("Encrypt: Data Index: " + i);
encrypt(data);
System.err.println("Decrypt: Data Index: " + i);
decrypt(data);
}
i++;
}
}
// Setup data for encryption
void encrypt(Data data) throws Exception {
byte[] input, output;
input = data.pt;
output = new byte[data.ct.length + data.tag.length];
System.arraycopy(data.ct, 0, output, 0, data.ct.length);
System.arraycopy(data.tag, 0, output, data.ct.length,
data.tag.length);
// Test different input/output buffers
System.err.println("\tinput len: " + input.length + " inOfs " +
inOfs + " outOfs " + outOfs + " in/out buffer: different");
crypto(true, data, input, output);
// Test with in-place buffers
if (same) {
System.err.println("\tinput len: " + input.length + " inOfs " +
inOfs + " outOfs " + outOfs + " in/out buffer: in-place");
cryptoSameBuffer(true, data, input, output);
}
}
// Setup data for decryption
void decrypt(Data data) throws Exception {
byte[] input, output;
input = new byte[data.ct.length + data.tag.length];
System.arraycopy(data.ct, 0, input, 0, data.ct.length);
System.arraycopy(data.tag, 0, input, data.ct.length, data.tag.length);
output = data.pt;
// Test different input/output buffers
System.err.println("\tinput len: " + input.length + " inOfs " +
inOfs + " outOfs " + outOfs + " in/out buffer: different");
crypto(false, data, input, output);
// Test with in-place buffers
if (same) {
System.err.println("\tinput len: " + input.length + " inOfs " +
inOfs + " outOfs " + outOfs + " in-place: same");
cryptoSameBuffer(false, data, input, output);
}
}
static AlgorithmParameterSpec getAPS(String algo, int tLen, byte[] iv) {
return switch (algo) {
case "AES", "AES/GCM/NoPadding" ->
new GCMParameterSpec(tLen * 8, iv);
case "CC20", "ChaCha20-Poly1305" -> new IvParameterSpec(iv);
default -> null;
};
}
/**
* Perform cipher operation using different input and output buffers.
* This method allows mixing of data types (byte, heap, direct).
*/
void crypto(boolean encrypt, Data d, byte[] input, byte[] output)
throws Exception {
byte[] pt = new byte[input.length + inOfs];
System.arraycopy(input, 0, pt, inOfs, input.length);
byte[] expectedOut = new byte[output.length + outOfs];
System.arraycopy(output, 0, expectedOut, outOfs, output.length);
int plen = input.length / ops.size(); // partial input length
int theoreticallen;// expected output length
int dataoffset = 0; // offset of unconsumed data in pt
int index = 0; // index of which op we are on
int rlen; // result length
int pbuflen = 0; // plen remaining in the internal buffers
Cipher cipher = Cipher.getInstance(algo);
cipher.init((encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE),
d.key, getAPS(algo, d.tag.length, d.iv));
cipher.updateAAD(d.aad);
ByteArrayOutputStream ba = new ByteArrayOutputStream();
ba.write(new byte[outOfs], 0, outOfs);
for (dtype v : ops) {
if (index < ops.size() - 1) {
if (sizes != null && input.length > 0) {
if (sizes[index] == -1) {
plen = input.length - dataoffset;
} else {
if (sizes[index] > input.length) {
plen = input.length;
} else {
plen = sizes[index];
}
}
}
int olen = cipher.getOutputSize(plen) + outOfs;
/*
* The theoretical limit is the length of the data sent to
* update() + any data might be setting in CipherCore or AEAD
* internal buffers % the block size.
*/
theoreticallen = (plen + pbuflen) - (d.blockSize > 0 ?
(plen + pbuflen) % d.blockSize : 0);
// Update operations
switch (v) {
case BYTE -> {
byte[] out = new byte[olen];
rlen = cipher.update(pt, dataoffset + inOfs, plen, out,
outOfs);
ba.write(out, outOfs, rlen);
}
case HEAP -> {
ByteBuffer b = ByteBuffer.allocate(plen + outOfs);
b.position(outOfs);
b.put(pt, dataoffset + inOfs, plen);
b.flip();
b.position(outOfs);
ByteBuffer out = ByteBuffer.allocate(olen);
out.position(outOfs);
rlen = cipher.update(b, out);
ba.write(out.array(), outOfs, rlen);
}
case DIRECT -> {
ByteBuffer b = ByteBuffer.allocateDirect(plen + outOfs);
b.position(outOfs);
b.put(pt, dataoffset + inOfs, plen);
b.flip();
b.position(outOfs);
ByteBuffer out = ByteBuffer.allocateDirect(olen);
out.position(outOfs);
rlen = cipher.update(b, out);
byte[] o = new byte[rlen];
out.flip();
out.position(outOfs);
out.get(o, 0, rlen);
ba.write(o);
}
default -> throw new Exception("Unknown op: " + v.name());
}
if (theoreticalCheck) {
pbuflen += plen - rlen;
if (encrypt && rlen != theoreticallen) {
throw new Exception("Wrong update return len (" +
v.name() + "): " + "rlen=" + rlen +
", expected output len=" + theoreticallen);
}
}
dataoffset += plen;
index++;
} else {
// doFinal operation
plen = input.length - dataoffset;
int olen = cipher.getOutputSize(plen) + outOfs;
switch (v) {
case BYTE -> {
byte[] out = new byte[olen];
rlen = cipher.doFinal(pt, dataoffset + inOfs,
plen, out, outOfs);
ba.write(out, outOfs, rlen);
}
case HEAP -> {
ByteBuffer b = ByteBuffer.allocate(plen + inOfs);
b.limit(b.capacity());
b.position(inOfs);
b.put(pt, dataoffset + inOfs, plen);
b.flip();
b.position(inOfs);
ByteBuffer out = ByteBuffer.allocate(olen);
out.limit(out.capacity());
out.position(outOfs);
rlen = cipher.doFinal(b, out);
ba.write(out.array(), outOfs, rlen);
}
case DIRECT -> {
ByteBuffer b = ByteBuffer.allocateDirect(plen + inOfs);
b.limit(b.capacity());
b.position(inOfs);
b.put(pt, dataoffset + inOfs, plen);
b.flip();
b.position(inOfs);
ByteBuffer out = ByteBuffer.allocateDirect(olen);
out.limit(out.capacity());
out.position(outOfs);
rlen = cipher.doFinal(b, out);
byte[] o = new byte[rlen];
out.flip();
out.position(outOfs);
out.get(o, 0, rlen);
ba.write(o);
}
default -> throw new Exception("Unknown op: " + v.name());
}
if (theoreticalCheck && rlen != olen - outOfs) {
throw new Exception("Wrong doFinal return len (" +
v.name() + "): " + "rlen=" + rlen +
", expected output len=" + (olen - outOfs));
}
// Verify results
byte[] ctresult = ba.toByteArray();
if (ctresult.length != expectedOut.length ||
Arrays.compare(ctresult, expectedOut) != 0) {
String s = "Ciphertext mismatch (" + v.name() +
"):\nresult (len=" + ctresult.length + "): " +
hex.formatHex(ctresult) +
"\nexpected (len=" + output.length + "): " +
hex.formatHex(output);
System.err.println(s);
throw new Exception(s);
}
}
}
}
/**
* Perform cipher operation using in-place buffers. This method does not
* allow mixing of data types (byte, heap, direct).
*
* Mixing data types makes no sense for in-place operations and would
* greatly complicate the test code.
*/
void cryptoSameBuffer(boolean encrypt, Data d, byte[] input, byte[] output) throws Exception {
byte[] data, out;
if (encrypt) {
data = new byte[output.length + Math.max(inOfs, outOfs)];
} else {
data = new byte[input.length + Math.max(inOfs, outOfs)];
}
ByteBuffer bbin = null, bbout = null;
System.arraycopy(input, 0, data, inOfs, input.length);
byte[] expectedOut = new byte[output.length + outOfs];
System.arraycopy(output, 0, expectedOut, outOfs, output.length);
int plen = input.length / ops.size(); // partial input length
int theorticallen = plen -
(d.blockSize > 0 ? plen % d.blockSize : 0); // output length
int dataoffset = 0;
int index = 0;
int rlen = 0; // result length
int len = 0;
Cipher cipher = Cipher.getInstance(algo);
cipher.init((encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE),
d.key, getAPS(algo, d.tag.length, d.iv));
cipher.updateAAD(d.aad);
// Prepare data
switch (ops.get(0)) {
case HEAP -> {
bbin = ByteBuffer.wrap(data);
bbin.limit(input.length + inOfs);
bbout = bbin.duplicate();
}
case DIRECT -> {
bbin = ByteBuffer.allocateDirect(data.length);
bbout = bbin.duplicate();
bbin.put(data, 0, input.length + inOfs);
bbin.flip();
}
}
// Set data limits for bytebuffers
if (bbin != null) {
bbin.position(inOfs);
bbout.limit(output.length + outOfs);
bbout.position(outOfs);
}
// Iterate through each operation
for (dtype v : ops) {
if (index < ops.size() - 1) {
switch (v) {
case BYTE -> {
rlen = cipher.update(data, dataoffset + inOfs, plen,
data, len + outOfs);
}
case HEAP, DIRECT -> {
theorticallen = bbin.remaining() - (d.blockSize > 0 ?
bbin.remaining() % d.blockSize : 0);
rlen = cipher.update(bbin, bbout);
}
default -> throw new Exception("Unknown op: " + v.name());
}
// Check that the theoretical return value matches the actual.
if (theoreticalCheck && encrypt && rlen != theorticallen) {
throw new Exception("Wrong update return len (" +
v.name() + "): " + "rlen=" + rlen +
", expected output len=" + theorticallen);
}
dataoffset += plen;
len += rlen;
index++;
} else {
// Run doFinal op
plen = input.length - dataoffset;
switch (v) {
case BYTE -> {
rlen = cipher.doFinal(data, dataoffset + inOfs,
plen, data, len + outOfs);
out = Arrays.copyOfRange(data, 0,len + rlen + outOfs);
}
case HEAP, DIRECT -> {
rlen = cipher.doFinal(bbin, bbout);
bbout.flip();
out = new byte[bbout.remaining()];
bbout.get(out);
}
default -> throw new Exception("Unknown op: " + v.name());
}
len += rlen;
// Verify results
if (len != output.length ||
Arrays.compare(out, 0, len, expectedOut, 0,
output.length) != 0) {
String s = "Ciphertext mismatch (" + v.name() +
"):\nresult (len=" + len + "):\n" +
hex.formatHex(out) +
"\nexpected (len=" + output.length + "):\n" +
hex.formatHex(output);
System.err.println(s);
throw new Exception(s);
}
}
}
}
static void offsetTests(AEADBufferTest t) throws Exception {
t.clone().offset(2).test();
t.clone().inOfs(2).test();
// Test not designed for overlap situations
t.clone().outOfs(2).differentBufferOnly().test();
}
public static void main(String args[]) throws Exception {
AEADBufferTest t;
initTest();
// **** GCM Tests
// Test single byte array
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE)));
// Test update-doFinal with byte arrays
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE)));
// Test update-update-doFinal with byte arrays
new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)));
// Test single heap bytebuffer
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP)));
// Test update-doFinal with heap bytebuffer
new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.HEAP, dtype.HEAP)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP, dtype.HEAP)));
// Test update-update-doFinal with heap bytebuffer
new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)));
// Test single direct bytebuffer
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.DIRECT)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.DIRECT)));
// Test update-doFinal with direct bytebuffer
new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.DIRECT)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.DIRECT)));
// Test update-update-doFinal with direct bytebuffer
new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).test();
offsetTests(new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)));
// Test update-update-doFinal with byte arrays and preset data sizes
t = new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).dataSegments(
new int[] { 1, 1, AEADBufferTest.REMAINDER});
t.clone().test();
offsetTests(t.clone());
// Test update-doFinal with a byte array and a direct bytebuffer
t = new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.BYTE, dtype.DIRECT)).differentBufferOnly();
t.clone().test();
offsetTests(t.clone());
// Test update-doFinal with a byte array and heap and direct bytebuffer
t = new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.BYTE, dtype.HEAP, dtype.DIRECT)).differentBufferOnly();
t.clone().test();
offsetTests(t.clone());
// Test update-doFinal with a direct bytebuffer and a byte array.
t = new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly();
t.clone().test();
offsetTests(t.clone());
// Test update-doFinal with a direct bytebuffer and a byte array with
// preset data sizes.
t = new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly().
dataSegments(new int[] { 20, AEADBufferTest.REMAINDER });
t.clone().test();
offsetTests(t.clone());
// Test update-update-doFinal with a direct and heap bytebuffer and a
// byte array with preset data sizes.
t = new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.BYTE, dtype.HEAP)).
differentBufferOnly().dataSet(5).
dataSegments(new int[] { 5000, 1000, AEADBufferTest.REMAINDER });
t.clone().test();
offsetTests(t.clone());
// Test update-update-doFinal with byte arrays, incrementing through
// every data size combination for the Data set 0
new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).incrementalSegments().
dataSet(0).test();
// Test update-update-doFinal with direct bytebuffers, incrementing through
// every data size combination for the Data set 0
new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
incrementalSegments().dataSet(0).test();
new AEADBufferTest("AES/GCM/NoPadding",
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
dataSegments(new int[] { 49, 0, 2 }).dataSet(0).test();
// **** CC20P1305 Tests
// Test single byte array
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE)));
// Test update-doFinal with byte arrays
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE)));
// Test update-update-doFinal with byte arrays
new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)));
// Test single heap bytebuffer
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP)));
// Test update-doFinal with heap bytebuffer
new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.HEAP, dtype.HEAP)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP, dtype.HEAP)));
// Test update-update-doFinal with heap bytebuffer
new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)));
// Test single direct bytebuffer
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.DIRECT)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.DIRECT)));
// Test update-doFinal with direct bytebuffer
new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.DIRECT)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.DIRECT)));
// Test update-update-doFinal with direct bytebuffer
new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).test();
offsetTests(new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)));
// Test update-update-doFinal with byte arrays and preset data sizes
t = new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).dataSegments(
new int[] { 1, 1, AEADBufferTest.REMAINDER});
t.clone().test();
offsetTests(t.clone());
// Test update-doFinal with a byte array and a direct bytebuffer
t = new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.BYTE, dtype.DIRECT)).differentBufferOnly();
t.clone().test();
offsetTests(t.clone());
// Test update-doFinal with a byte array and heap and direct bytebuffer
t = new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.BYTE, dtype.HEAP, dtype.DIRECT)).differentBufferOnly();
t.clone().test();
offsetTests(t.clone());
// Test update-doFinal with a direct bytebuffer and a byte array.
t = new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly();
t.clone().test();
offsetTests(t.clone());
// Test update-doFinal with a direct bytebuffer and a byte array with
// preset data sizes.
t = new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly().
dataSegments(new int[] { 20, AEADBufferTest.REMAINDER });
t.clone().test();
offsetTests(t.clone());
// Test update-update-doFinal with a direct and heap bytebuffer and a
// byte array with preset data sizes.
t = new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.BYTE, dtype.HEAP)).
differentBufferOnly().dataSet(1).
dataSegments(new int[] { 5000, 1000, AEADBufferTest.REMAINDER });
t.clone().test();
offsetTests(t.clone());
// Test update-update-doFinal with byte arrays, incrementing through
// every data size combination for the Data set 0
new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).incrementalSegments().
dataSet(0).test();
// Test update-update-doFinal with direct bytebuffers, incrementing through
// every data size combination for the Data set 0
new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
incrementalSegments().dataSet(0).test();
new AEADBufferTest("ChaCha20-Poly1305",
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
dataSegments(new int[] { 49, 0, 2 }).dataSet(0).test();
}
// Test data
static void initTest() {
datamap.put("AES/GCM/NoPadding", List.of(
// GCM KAT
new Data(AES, 0,
"141f1ce91989b07e7eb6ae1dbd81ea5e",
"49451da24bd6074509d3cebc2c0394c972e6934b45a1d91f3ce1d3ca69e19" +
"4aa1958a7c21b6f21d530ce6d2cc5256a3f846b6f9d2f38df0102c4791e5" +
"7df038f6e69085646007df999751e248e06c47245f4cd3b8004585a7470d" +
"ee1690e9d2d63169a58d243c0b57b3e5b4a481a3e4e8c60007094ef3adea" +
"2e8f05dd3a1396f",
"d384305af2388699aa302f510913fed0f2cb63ba42efa8c5c9de2922a2ec" +
"2fe87719dadf1eb0aef212b51e74c9c5b934104a43",
"630cf18a91cc5a6481ac9eefd65c24b1a3c93396bd7294d6b8ba3239517" +
"27666c947a21894a079ef061ee159c05beeb4",
"f4c34e5fbe74c0297313268296cd561d59ccc95bbfcdfcdc71b0097dbd83" +
"240446b28dc088abd42b0fc687f208190ff24c0548",
"dbb93bbb56d0439cd09f620a57687f5d"),
// GCM KAT
new Data(AES, 1, "11754cd72aec309bf52f7687212e8957",
"3c819d9a9bed087615030b65",
new byte[0], null, null,
"250327c674aaf477aef2675748cf6971"),
// Random test data
new Data(AES, 4, "272f16edb81a7abbea887357a58c1917",
"794ec588176c703d3d2a7a07",
new byte[2075], null,
"15b461672153270e8ba1e6789f7641c5411f3e642abda731b6086f535c216457" +
"e87305bc59a1ff1f7e1e0bbdf302b75549b136606c67d7e5f71277aeca4bc670" +
"07a98f78e0cfa002ed183e62f07893ad31fe67aad1bb37e15b957a14d145f14f" +
"7483d041f2c3612ad5033155984470bdfc64d18df73c2745d92f28461bb09832" +
"33524811321ba87d213692825815dd13f528dba601a3c319cac6be9b48686c23" +
"a0ce23d5062916ea8827bbb243f585e446131489e951354c8ab24661f625c02e" +
"15536c5bb602244e98993ff745f3e523399b2059f0e062d8933fad2366e7e147" +
"510a931282bb0e3f635efe7bf05b1dd715f95f5858261b00735224256b6b3e80" +
"7364cb53ff6d4e88f928cf67ac70da127718a8a35542efbae9dd7567c818a074" +
"9a0c74bd69014639f59768bc55056d1166ea5523e8c66f9d78d980beb8f0d83b" +
"a9e2c5544b94dc3a1a4b6f0f95f897b010150e89ebcacf0daee3c2793d6501a0" +
"b58b411de273dee987e8e8cf8bb29ef2e7f655b46b55fabf64c6a4295e0d080b" +
"6a570ace90eb0fe0f5b5d878bdd90eddaa1150e4d5a6505b350aac814fe99615" +
"317ecd0516a464c7904011ef5922409c0d65b1e43b69d7c3293a8f7d3e9fbee9" +
"eb91ec0007a7d6f72e64deb675d459c5ba07dcfd58d08e6820b100465e6e04f0" +
"663e310584a00d36d23699c1bffc6afa094c75184fc7cde7ad35909c0f49f2f3" +
"fe1e6d745ab628d74ea56b757047de57ce18b4b3c71e8af31a6fac16189cb0a3" +
"a97a1bea447042ce382fcf726560476d759c24d5c735525ea26a332c2094408e" +
"671c7deb81d5505bbfd178f866a6f3a011b3cfdbe089b4957a790688028dfdf7" +
"9a096b3853f9d0d6d3feef230c7f5f46ffbf7486ebdaca5804dc5bf9d202415e" +
"e0d67b365c2f92a17ea740807e4f0b198b42b54f15faa9dff2c7c35d2cf8d72e" +
"b8f8b18875a2e7b5c43d1e0aa5139c461e8153c7f632895aa46ffe2b134e6a0d" +
"dfbf6a336e709adfe951bd52c4dfc7b07a15fb3888fc35b7e758922f87a104c4" +
"563c5c7839cfe5a7edbdb97264a7c4ebc90367b10cbe09dbf2390767ad7afaa8" +
"8fb46b39d3f55f216d2104e5cf040bf3d39b758bea28e2dbce576c808d17a8eb" +
"e2fd183ef42a774e39119dff1f539efeb6ad15d889dfcb0d54d0d4d4cc03c8d9" +
"aa6c9ebd157f5e7170183298d6a30ada8792dcf793d931e2a1eafccbc63c11c0" +
"c5c5ed60837f30017d693ccb294df392a8066a0594a56954aea7b78a16e9a11f" +
"4a8bc2104070a7319f5fab0d2c4ccad8ec5cd8f47c839179bfd54a7bf225d502" +
"cd0a318752fe763e8c09eb88fa57fc5399ad1f797d0595c7b8afdd23f13603e9" +
"6802192bb51433b7723f4e512bd4f799feb94b458e7f9792f5f9bd6733828f70" +
"a6b7ffbbc0bb7575021f081ec2a0d37fecd7cda2daec9a3a9d9dfe1c8034cead" +
"e4b56b581cc82bd5b74b2b30817967d9da33850336f171a4c68e2438e03f4b11" +
"96da92f01b3b7aeab795180ccf40a4b090b1175a1fc0b67c95f93105c3aef00e" +
"13d76cc402539192274fee703730cd0d1c5635257719cc96cacdbad00c6255e2" +
"bd40c775b43ad09599e84f2c3205d75a6661ca3f151183be284b354ce21457d1" +
"3ba65b9b2cdb81874bd14469c2008b3ddec78f7225ecc710cc70de7912ca6a6d" +
"348168322ab59fdafcf5c833bfa0ad4046f4b6da90e9f263db7079af592eda07" +
"5bf16c6b1a8346da9c292a48bf660860a4fc89eaef40bc132779938eca294569" +
"787c740af2b5a8de7f5e10ac750d1e3d0ef3ed168ba408a676e10b8a20bd4be8" +
"3e8336b45e54481726d73e1bd19f165a98e242aca0d8387f2dd22d02d74e23db" +
"4cef9a523587413e0a44d7e3260019a34d3a6b38426ae9fa4655be338d721970" +
"cb9fe76c073f26f9303093a033022cd2c62b2790bce633ba9026a1c93b6535f1" +
"1882bf5880e511b9e1b0b7d8f23a993aae5fd275faac3a5b4ccaf7c06b0b266a" +
"ee970a1e3a4cd7a41094f516960630534e692545b25a347c30e3f328bba4825f" +
"ed754e5525d846131ecba7ca120a6aeabc7bab9f59c890c80b7e31f9bc741591" +
"55d292433ce9558e104102f2cc63ee267c1c8333e841522707ea6d595cb802b9" +
"61697da77bbc4cb404ea62570ab335ebffa2023730732ac5ddba1c3dbb5be408" +
"3c50aea462c1ffa166d7cc3db4b742b747e81b452db2363e91374dee8c6b40f0" +
"e7fbf50e60eaf5cc5649f6bb553aae772c185026ceb052af088c545330a1ffbf" +
"50615b8c7247c6cd386afd7440654f4e15bcfae0c45442ec814fe88433a9d616" +
"ee6cc3f163f0d3d325526d05f25d3b37ad5eeb3ca77248ad86c9042b16c65554" +
"aebb6ad3e17b981492b13f42c5a5dc088e991da303e5a273fdbb8601aece4267" +
"47b01f6cb972e6da1743a0d7866cf206e95f23c6f8e337c901b9cd34a9a1fbbe" +
"1694f2c26b00dfa4d02c0d54540163e798fbdc9c25f30d6406f5b4c13f7ed619" +
"34e350f4059c13aa5e973307a9e3058917cda96fdd082e9c629ccfb2a9f98d12" +
"5c6e4703a7b0f348f5cdeb63cef2133d1c6c1a087591e0a2bca29d09c6565e66" +
"e91042f83b0e74e60a5d57562c23e2fbcd6599c29d7c19e47cf625c2ce24bb8a" +
"13f8e54041498437eec2cedd1e3d8e57a051baa962c0a62d70264d99c5ee716d" +
"5c8b9078db08c8b2c5613f464198a7aff43f76c5b4612b46a4f1cd2a494386c5" +
"7fd28f3d199f0ba8d8e39116cc7db16ce6188205ee49a9dce3d4fa32ea394919" +
"f6e91ef58b84d00b99596b4306c2d9f432d917bb4ac73384c42ae12adb4920d8" +
"c33a816febcb299dcddf3ec7a8eb6e04cdc90891c6e145bd9fc5f41dc4061a46" +
"9feba38545b64ec8203f386ceef52785619e991d274ae80af7e54af535e0b011" +
"5effdf847472992875e09398457604d04e0bb965db692c0cdcf11a",
"687cc09c89298491deb51061d709af"),
// Randomly generated data at the time of execution.
new Data(AES, 5, "11754cd72aec309bf52f7687212e8957",
16, 12345)));
datamap.put("ChaCha20-Poly1305", List.of(
new Data("CC20", 0,
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
"070000004041424344454647",
1,
"4c616469657320616e642047656e746c656d656e206f662074686520636c6173" +
"73206f66202739393a204966204920636f756c64206f6666657220796f75206f" +
"6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" +
"637265656e20776f756c642062652069742e",
"50515253c0c1c2c3c4c5c6c7",
"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6" +
"3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36" +
"92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc" +
"3ff4def08e4b7a9de576d26586cec64b61161ae10b59",
"4f09e26a7e902ecbd0600691"),
// Randomly generated data at the time of execution.
new Data("CC20", 1,
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
12, 12345)));
}
}

View file

@ -0,0 +1,759 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HexFormat;
import java.util.List;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
/*
* @test
* @bug 8048596
* @summary AEAD encryption/decryption test
*/
/*
* The test does the following:
* - create an input text and additional data
* - generate a secret key
* - instantiate a cipher according to the GCM transformation
* - generate an outputText using a single-part encryption/decryption
* in AEAD mode
* - perform 16 different combinations of multiple-part encryption/decryption
* operation in AEAD mode (in encryption mode new Cipher object is created
* and initialized with the same secret key and parameters)
* - check that all 17 results are equal
*
* Combinations:
*
* combination #1
* updateAAD(byte[] src)
* update(byte[], int, int)
* doFinal(byte[], int, int)
*
* combination #2
* updateAAD(byte[] src)
* update(byte[], int, int)
* doFinal(byte[], int, int, byte[], int)
*
* combination #3
* updateAAD(byte[] src)
* update(byte[], int, int, byte[], int)
* doFinal(byte[], int, int)
*
* combination #4
* updateAAD(byte[] src)
* update(byte[], int, int, byte[], int)
* doFinal(byte[], int, int, byte[], int)
*
* combination #5 - #8 are similar to #1 -#4,
* but with updateAAD(byte[] src, int offset, int len)
*
* combination #9 - #12 are similar to #1 - #4,
* but with updateAAD(ByteBuffer src)
*
* combination #13 - #16 are similar to #9 - #12 but with directly allocated
* ByteBuffer and update(ByteBuffer input, ByteBuffer output)
*
*/
public class Encrypt {
private static final String ALGORITHMS[] = { "AES" };
private static final int KEY_STRENGTHS[] = { 128, 192, 256 };
private static final int TEXT_LENGTHS[] = { 0, 256, 1024 };
private static final int AAD_LENGTHS[] = { 0, 8, 128, 256, 1024 };
private static final int ARRAY_OFFSET = 8;
private final String transformation;
private final Provider provider;
private final SecretKey key;
private final int textLength;
private final int AADLength;
/**
* @param provider Security provider
* @param algorithm Security algorithm to test
* @param mode The mode (GCM is only expected)
* @param padding Algorithm padding
* @param keyStrength key length
* @param textLength Plain text length
* @param AADLength Additional data length
*/
public Encrypt(Provider provider, String algorithm, String mode,
String padding, int keyStrength, int textLength, int AADLength)
throws Exception {
// init a secret Key
KeyGenerator kg = KeyGenerator.getInstance(algorithm, provider);
kg.init(keyStrength);
key = kg.generateKey();
this.provider = provider;
this.transformation = algorithm + "/" + mode + "/" + padding;
this.textLength = textLength;
this.AADLength = AADLength;
}
public static void main(String[] args) throws Exception {
Provider p = Security.getProvider(
System.getProperty("test.provider.name", "SunJCE"));
for (String alg : ALGORITHMS) {
for (int keyStrength : KEY_STRENGTHS) {
if (keyStrength > Cipher.getMaxAllowedKeyLength(alg)) {
// skip this if this key length is larger than what's
// configured in the JCE jurisdiction policy files
continue;
}
for (int textLength : TEXT_LENGTHS) {
for (int AADLength : AAD_LENGTHS) {
Encrypt test = new Encrypt(p, alg,
"GCM", "NoPadding", keyStrength, textLength,
AADLength);
Cipher cipher = test.createCipher(Cipher.ENCRYPT_MODE,
null);
AlgorithmParameters params = cipher.getParameters();
test.doTest(params);
System.out.println("Test " + alg + ":"
+ keyStrength + ":" + textLength + ":"
+ AADLength + " passed");
}
}
}
}
}
public void doTest(AlgorithmParameters params) throws Exception {
System.out.println("Test transformation = " + transformation
+ ", textLength = " + textLength
+ ", AADLength = " + AADLength);
byte[] input = Helper.generateBytes(textLength);
byte[] AAD = Helper.generateBytes(AADLength);
byte[] result = execute(Cipher.ENCRYPT_MODE, AAD, input, params);
result = execute(Cipher.DECRYPT_MODE, AAD, result, params);
if (!Arrays.equals(input, result)) {
throw new RuntimeException("Test failed");
}
System.out.println("Test passed");
}
/**
* Create a Cipher object for the requested encryption/decryption mode.
*
* @param mode encryption or decryption mode
* @return Cipher object initiated to perform requested mode operation
*/
private Cipher createCipher(int mode, AlgorithmParameters params)
throws Exception {
Cipher ci;
if (Cipher.ENCRYPT_MODE == mode) {
// create a new Cipher object for encryption
ci = Cipher.getInstance(transformation, provider);
// initiate it with the saved parameters
if (params != null) {
ci.init(Cipher.ENCRYPT_MODE, key, params);
} else {
// initiate the cipher without parameters
ci.init(Cipher.ENCRYPT_MODE, key);
}
} else {
// it is expected that parameters already generated
// before decryption
ci = Cipher.getInstance(transformation, provider);
ci.init(Cipher.DECRYPT_MODE, key, params);
}
return ci;
}
/**
* Test AEAD combinations
*
* @param mode decryption or encryption
* @param AAD additional data for AEAD operations
* @param inputText plain text to decrypt/encrypt
* @return output text after encrypt/decrypt
*/
public byte[] execute(int mode, byte[] AAD, byte[] inputText,
AlgorithmParameters params) throws Exception {
Cipher cipher = createCipher(mode, params);
// results of each combination will be saved in the outputTexts
List<byte[]> outputTexts = new ArrayList<>();
// generate a standard outputText using a single-part en/de-cryption
cipher.updateAAD(AAD);
byte[] output = cipher.doFinal(inputText);
// execute multiple-part encryption/decryption combinations
combination_1(outputTexts, mode, AAD, inputText, params);
combination_2(outputTexts, mode, AAD, inputText, params);
combination_3(outputTexts, mode, AAD, inputText, params);
combination_4(outputTexts, mode, AAD, inputText, params);
combination_5(outputTexts, mode, AAD, inputText, params);
combination_6(outputTexts, mode, AAD, inputText, params);
combination_7(outputTexts, mode, AAD, inputText, params);
combination_8(outputTexts, mode, AAD, inputText, params);
combination_9(outputTexts, mode, AAD, inputText, params);
combination_10(outputTexts, mode, AAD, inputText, params);
combination_11(outputTexts, mode, AAD, inputText, params);
combination_12(outputTexts, mode, AAD, inputText, params);
combination_13(outputTexts, mode, AAD, inputText, params);
combination_14(outputTexts, mode, AAD, inputText, params);
combination_15(outputTexts, mode, AAD, inputText, params);
combination_16(outputTexts, mode, AAD, inputText, params);
for (int k = 0; k < outputTexts.size(); k++) {
HexFormat hex = HexFormat.of().withUpperCase();
if (!Arrays.equals(output, outputTexts.get(k))) {
System.out.println("Combination #" + (k + 1) + "\nresult " +
hex.formatHex(outputTexts.get(k)) +
"\nexpected: " + hex.formatHex(output));
throw new RuntimeException("Combination #" + (k + 1) + " failed");
}
}
return output;
}
/*
* Execute multiple-part encryption/decryption combination #1:
* updateAAD(byte[] src)
* update(byte[], int, int)
* doFinal(byte[], int, int)
*/
private void combination_1(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher c = createCipher(mode, params);
c.updateAAD(AAD);
byte[] part11 = c.update(plainText, 0, plainText.length);
int part11_length = part11 == null ? 0 : part11.length;
byte[] part12 = c.doFinal();
byte[] outputText1 = new byte[part11_length + part12.length];
if (part11 != null) {
System.arraycopy(part11, 0, outputText1, 0, part11_length);
}
System.arraycopy(part12, 0, outputText1, part11_length, part12.length);
results.add(outputText1);
}
/*
* Execute multiple-part encryption/decryption combination #2:
* updateAAD(byte[] src)
* update(byte[], int, int)
* doFinal(byte[], int, int, byte[], int)
*/
private void combination_2(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher c = createCipher(mode, params);
c.updateAAD(AAD);
int t = 0;
int offset = 0;
if (plainText.length > ARRAY_OFFSET) {
t = plainText.length - ARRAY_OFFSET;
offset = ARRAY_OFFSET;
}
byte[] part21 = c.update(plainText, 0, t);
byte[] part22 = new byte[c.getOutputSize(plainText.length)];
int len2 = c.doFinal(plainText, t, offset, part22, 0);
int part21Length = part21 != null ? part21.length : 0;
byte[] outputText2 = new byte[part21Length + len2];
if (part21 != null) {
System.arraycopy(part21, 0, outputText2, 0, part21Length);
}
System.arraycopy(part22, 0, outputText2, part21Length, len2);
results.add(outputText2);
}
/*
* Execute multiple-part encryption/decryption combination #3
* updateAAD(byte[] src)
* update(byte[], int, int, byte[], int)
* doFinal(byte[], int, int)
*/
private void combination_3(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher ci = createCipher(mode, params);
ci.updateAAD(AAD);
byte[] part31 = new byte[ci.getOutputSize(plainText.length)];
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
int len = ci.update(plainText, 0, plainText.length - offset, part31, 0);
byte[] part32 = ci.doFinal(plainText, plainText.length - offset,
offset);
byte[] outputText3 = new byte[len + part32.length];
System.arraycopy(part31, 0, outputText3, 0, len);
System.arraycopy(part32, 0, outputText3, len, part32.length);
results.add(outputText3);
}
/*
* Execute multiple-part encryption/decryption combination #4:
* updateAAD(byte[] src)
* update(byte[], int, int, byte[], int)
* doFinal(byte[], int, int, byte[], int)
*/
private void combination_4(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher ci = createCipher(mode, params);
ci.updateAAD(AAD);
byte[] part41 = new byte[ci.getOutputSize(plainText.length)];
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
int len = ci.update(plainText, 0, plainText.length - offset, part41, 0);
int rest4 = ci.doFinal(plainText, plainText.length - offset, offset,
part41, len);
byte[] outputText4 = new byte[len + rest4];
System.arraycopy(part41, 0, outputText4, 0, outputText4.length);
results.add(outputText4);
}
/*
* Execute multiple-part encryption/decryption combination #5:
* updateAAD(byte[] src, int offset, int len)
* update(byte[], int, int)
* doFinal(byte[], int, int)
*/
private void combination_5(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher c = createCipher(mode, params);
c.updateAAD(AAD, 0, AAD.length);
byte[] part51 = c.update(plainText, 0, plainText.length);
byte[] part52 = c.doFinal();
int part51Length = part51 != null ? part51.length : 0;
byte[] outputText5 = new byte[part51Length + part52.length];
if (part51 != null) {
System.arraycopy(part51, 0, outputText5, 0, part51Length);
}
System.arraycopy(part52, 0, outputText5, part51Length, part52.length);
results.add(outputText5);
}
/*
* Execute multiple-part encryption/decryption combination #6:
* updateAAD(byte[] src, int offset, int len)
* updateAAD(byte[] src, int offset, int len)
* update(byte[], int, int) doFinal(byte[], int, int, byte[], int)
*/
private void combination_6(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher c = createCipher(mode, params);
c.updateAAD(AAD, 0, AAD.length / 2);
c.updateAAD(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
int t = 0;
int offset = 0;
if (plainText.length > ARRAY_OFFSET) {
t = plainText.length - ARRAY_OFFSET;
offset = ARRAY_OFFSET;
}
byte[] part61 = c.update(plainText, 0, t);
byte[] part62 = new byte[c.getOutputSize(plainText.length)];
int len = c.doFinal(plainText, t, offset, part62, 0);
int part61Length = part61 != null ? part61.length : 0;
byte[] outputText6 = new byte[part61Length + len];
if (part61 != null) {
System.arraycopy(part61, 0, outputText6, 0, part61Length);
}
System.arraycopy(part62, 0, outputText6, part61Length, len);
results.add(outputText6);
}
/*
* Execute multiple-part encryption/decryption combination #7
* updateAAD(byte[] src, int offset, int len)
* updateAAD(byte[] src, src.length, 0)
* update(byte[], int, int, byte[], int) doFinal(byte[],int, int)
*/
private void combination_7(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher ci = createCipher(mode, params);
ci.updateAAD(AAD, 0, AAD.length);
ci.updateAAD(AAD, AAD.length, 0);
byte[] part71 = new byte[ci.getOutputSize(plainText.length)];
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
int len = ci.update(plainText, 0, plainText.length - offset, part71, 0);
byte[] part72 = ci.doFinal(plainText, plainText.length - offset, offset);
byte[] outputText7 = new byte[len + part72.length];
System.arraycopy(part71, 0, outputText7, 0, len);
System.arraycopy(part72, 0, outputText7, len, part72.length);
results.add(outputText7);
}
/*
* Execute multiple-part encryption/decryption combination #8:
* updateAAD(byte[] src, 0, 0)
* updateAAD(byte[] src, 0, src.length)
* update(byte[], int, int, byte[], int)
* doFinal(byte[], int, int, byte[], int)
*/
private void combination_8(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher ci = createCipher(mode, params);
ci.updateAAD(AAD, 0, 0);
ci.updateAAD(AAD, 0, AAD.length);
byte[] part81 = new byte[ci.getOutputSize(plainText.length)];
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
int len = ci.update(plainText, 0, plainText.length - offset, part81, 0);
int rest = ci.doFinal(plainText, plainText.length - offset, offset,
part81, len);
byte[] outputText8 = new byte[len + rest];
System.arraycopy(part81, 0, outputText8, 0, outputText8.length);
results.add(outputText8);
}
/*
* Execute multiple-part encryption/decryption combination #9:
* updateAAD(ByteBuffer src)
* update(byte[], int, int) doFinal(byte[], int, int)
*/
private void combination_9(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
// prepare ByteBuffer to test
ByteBuffer buf = ByteBuffer.allocate(AAD.length);
buf.put(AAD);
buf.position(0);
buf.limit(AAD.length);
// Get Cipher object and do the combination
Cipher c = createCipher(mode, params);
c.updateAAD(buf);
byte[] part91 = c.update(plainText, 0, plainText.length);
int part91_length = part91 == null ? 0 : part91.length;
byte[] part92 = c.doFinal();
byte[] outputText9 = new byte[part91_length + part92.length];
// form result of the combination
if (part91 != null) {
System.arraycopy(part91, 0, outputText9, 0, part91_length);
}
System.arraycopy(part92, 0, outputText9, part91_length, part92.length);
results.add(outputText9);
}
/*
* Execute multiple-part encryption/decryption combination #10:
* updateAAD(ByteBuffer src)
* updateAAD(ByteBuffer src) update(byte[], int, int)
* doFinal(byte[], int, int, byte[], int)
*/
private void combination_10(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
// prepare ByteBuffer to test
ByteBuffer buf = ByteBuffer.allocate(AAD.length);
buf.put(AAD);
buf.position(0);
buf.limit(AAD.length / 2);
// get a Cipher object and do the combination
Cipher c = createCipher(mode, params);
// process the first half of AAD data
c.updateAAD(buf);
// process the rest of AAD data
buf.limit(AAD.length);
c.updateAAD(buf);
// prapare variables for the combination
int t = 0;
int offset = 0;
if (plainText.length > ARRAY_OFFSET) {
t = plainText.length - ARRAY_OFFSET;
offset = ARRAY_OFFSET;
}
// encrypt the text
byte[] part10_1 = c.update(plainText, 0, t);
int part10_1_Length = part10_1 != null ? part10_1.length : 0;
byte[] part10_2 = new byte[c.getOutputSize(plainText.length)];
int len2 = c.doFinal(plainText, t, offset, part10_2, 0);
// form the combination's result
byte[] outputText10 = new byte[part10_1_Length + len2];
if (part10_1 != null) {
System.arraycopy(part10_1, 0, outputText10, 0, part10_1_Length);
}
System.arraycopy(part10_2, 0, outputText10, part10_1_Length, len2);
results.add(outputText10);
}
/*
* Execute multiple-part encryption/decryption combination #11
* updateAAD(ByteBuffer src1)
* updateAAD(ByteBuffer src2)
* update(byte[],int, int, byte[], int)
* doFinal(byte[], int, int)
*/
private void combination_11(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
// prepare ByteBuffer1 to test
ByteBuffer buf1 = ByteBuffer.allocate(AAD.length / 2);
buf1.put(AAD, 0, AAD.length / 2);
buf1.position(0);
buf1.limit(AAD.length / 2);
// get a Cipher object and do combination
Cipher ci = createCipher(mode, params);
// process the first half of AAD data
ci.updateAAD(buf1);
// prepare ByteBuffer2 to test
ByteBuffer buf2 = ByteBuffer.allocate(AAD.length - AAD.length / 2);
buf2.put(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
buf2.position(0);
buf2.limit(AAD.length - AAD.length / 2);
// process the rest of AAD data
ci.updateAAD(buf2);
// encrypt plain text
byte[] part11_1 = new byte[ci.getOutputSize(plainText.length)];
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
int len_11 = ci.update(plainText, 0, plainText.length - offset,
part11_1, 0);
byte[] part11_2 = ci.doFinal(plainText, plainText.length - offset,
offset);
byte[] outputText11 = new byte[len_11 + part11_2.length];
System.arraycopy(part11_1, 0, outputText11, 0, len_11);
System.arraycopy(part11_2, 0, outputText11, len_11, part11_2.length);
results.add(outputText11);
}
/*
* Execute multiple-part encryption/decryption combination #12:
* updateAAD(ByteBuffer src)
* updateAAD(ByteBuffer emptyByteBuffer)
* update(byte[], int, int, byte[], int)
* doFinal(byte[], int, int, byte[], int)
*/
private void combination_12(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
// prepare ByteBuffer to test
ByteBuffer buf = ByteBuffer.allocate(AAD.length);
buf.put(AAD);
buf.position(0);
buf.limit(AAD.length);
Cipher ci = createCipher(mode, params);
ci.updateAAD(buf);
// prepare an empty ByteBuffer
ByteBuffer emptyBuf = ByteBuffer.allocate(0);
emptyBuf.put(new byte[0]);
ci.updateAAD(emptyBuf);
byte[] part12_1 = new byte[ci.getOutputSize(plainText.length)];
int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
int len12 = ci.update(plainText, 0, plainText.length - offset,
part12_1, 0);
int rest12 = ci.doFinal(plainText, plainText.length - offset, offset,
part12_1, len12);
byte[] outputText12 = new byte[len12 + rest12];
System.arraycopy(part12_1, 0, outputText12, 0, outputText12.length);
results.add(outputText12);
}
/*
* Execute multiple-part encryption/decryption combination #13:
* updateAAD(ByteBuffer src), where src is directly allocated
* update(ByteBuffer input, ByteBuffer out)
* doFinal(ByteBuffer input, ByteBuffer out)
*/
private void combination_13(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher c = createCipher(mode, params);
// prepare ByteBuffer to test
ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
buf.put(AAD);
buf.position(0);
buf.limit(AAD.length);
c.updateAAD(buf);
// prepare buffers to encrypt/decrypt
ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
in.put(plainText);
in.position(0);
in.limit(plainText.length);
ByteBuffer output = ByteBuffer.allocateDirect(
c.getOutputSize(in.limit()));
output.position(0);
output.limit(c.getOutputSize(in.limit()));
// process input text
c.update(in, output);
c.doFinal(in, output);
int resultSize = output.position();
byte[] result13 = new byte[resultSize];
output.position(0);
output.limit(resultSize);
output.get(result13, 0, resultSize);
results.add(result13);
}
/*
* Execute multiple-part encryption/decryption combination #14:
* updateAAD(ByteBuffer src) updateAAD(ByteBuffer src),
* where src is directly allocated
* update(ByteBuffer input, ByteBuffer out)
* doFinal(ByteBuffer input, ByteBuffer out)
*/
private void combination_14(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher c = createCipher(mode, params);
// prepare ByteBuffer to test
ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
buf.put(AAD);
// process the first half of AAD data
buf.position(0);
buf.limit(AAD.length / 2);
c.updateAAD(buf);
// process the rest of AAD data
buf.limit(AAD.length);
c.updateAAD(buf);
// prepare buffers to encrypt/decrypt
ByteBuffer in = ByteBuffer.allocate(plainText.length);
in.put(plainText);
in.position(0);
in.limit(plainText.length);
ByteBuffer out = ByteBuffer.allocate(c.getOutputSize(in.limit()));
out.position(0);
out.limit(c.getOutputSize(in.limit()));
// process input text
c.update(in, out);
c.doFinal(in, out);
int resultSize = out.position();
byte[] result14 = new byte[resultSize];
out.position(0);
out.limit(resultSize);
out.get(result14, 0, resultSize);
results.add(result14);
}
/*
* Execute multiple-part encryption/decryption combination #15
* updateAAD(ByteBuffer src1), where src1 is directly allocated
* updateAAD(ByteBuffer src2), where src2 is directly allocated
* doFinal(ByteBuffer input, ByteBuffer out)
*/
private void combination_15(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher c = createCipher(mode, params);
// prepare ByteBuffer1 to test
ByteBuffer buf1 = ByteBuffer.allocateDirect(AAD.length / 2);
buf1.put(AAD, 0, AAD.length / 2);
buf1.position(0);
buf1.limit(AAD.length / 2);
// process the first half of AAD data
c.updateAAD(buf1);
// prepare ByteBuffer2 to test
ByteBuffer buf2 = ByteBuffer.allocateDirect(
AAD.length - AAD.length / 2);
buf2.put(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
buf2.position(0);
buf2.limit(AAD.length - AAD.length / 2);
// process the rest of AAD data
c.updateAAD(buf2);
// prepare buffers to encrypt/decrypt
ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
in.put(plainText);
in.position(0);
in.limit(plainText.length);
ByteBuffer output = ByteBuffer.allocateDirect(
c.getOutputSize(in.limit()));
output.position(0);
output.limit(c.getOutputSize(in.limit()));
// process input text
c.doFinal(in, output);
int resultSize = output.position();
byte[] result15 = new byte[resultSize];
output.position(0);
output.limit(resultSize);
output.get(result15, 0, resultSize);
results.add(result15);
}
/*
* Execute multiple-part encryption/decryption combination #16:
* updateAAD(ByteBuffer src)
* updateAAD(ByteBuffer emptyByteBuffer)
* update(ByteBuffer input, ByteBuffer out)
* doFinal(EmptyByteBuffer, ByteBuffer out)
*/
private void combination_16(List<byte[]> results, int mode, byte[] AAD,
byte[] plainText, AlgorithmParameters params) throws Exception {
Cipher c = createCipher(mode, params);
// prepare ByteBuffer to test
ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
buf.put(AAD);
buf.position(0);
buf.limit(AAD.length);
c.updateAAD(buf);
// prepare empty ByteBuffer
ByteBuffer emptyBuf = ByteBuffer.allocateDirect(0);
emptyBuf.put(new byte[0]);
c.updateAAD(emptyBuf);
// prepare buffers to encrypt/decrypt
ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
in.put(plainText);
in.position(0);
in.limit(plainText.length);
ByteBuffer output = ByteBuffer.allocateDirect(
c.getOutputSize(in.limit()));
output.position(0);
output.limit(c.getOutputSize(in.limit()));
// process input text with an empty buffer
c.update(in, output);
ByteBuffer emptyBuf2 = ByteBuffer.allocate(0);
emptyBuf2.put(new byte[0]);
c.doFinal(emptyBuf2, output);
int resultSize = output.position();
byte[] result16 = new byte[resultSize];
output.position(0);
output.limit(resultSize);
output.get(result16, 0, resultSize);
results.add(result16);
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2020, 2024, 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.
*
* 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.
*/
import java.util.List;
/*
* @test
* @summary Uses AEADBufferTest to run a long test with incrementing through
* each byte in each byte array using AES GCM
* @run main/manual GCMIncrementByte4
*/
public class GCMIncrementByte4 {
public static void main(String args[]) throws Exception {
AEADBufferTest.initTest();
new AEADBufferTest("AES/GCM/NoPadding",
List.of(AEADBufferTest.dtype.BYTE, AEADBufferTest.dtype.BYTE,
AEADBufferTest.dtype.BYTE)).incrementalSegments().dataSet(4).
test();
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2020, 2024, 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.
*
* 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.
*/
import java.util.List;
/*
* @test
* @summary Uses AEADBufferTest to run a long test with incrementing through
* each byte in each direct bytebuffer using AES GCM
* @run main/manual GCMIncrementDirect4
*/
public class GCMIncrementDirect4 {
public static void main(String args[]) throws Exception {
AEADBufferTest.initTest();
new AEADBufferTest("AES/GCM/NoPadding",
List.of(AEADBufferTest.dtype.DIRECT, AEADBufferTest.dtype.DIRECT,
AEADBufferTest.dtype.DIRECT)).incrementalSegments().dataSet(4).
test();
}
}

View file

@ -0,0 +1,230 @@
/*
* Copyright (c) 2019, 2024, 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.
*
* 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.
*/
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.HashMap;
/*
* @test
* @bug 8220165
* @summary Verify correctness of large data sizes for GCM.
*/
/**
* This test stores the MD5 hash of correctly encrypted AES/GCM data for
* particular data lengths. Those lengths are run on SunJCE to verify returns
* the same MD5 hash of the encrypted data. These are not NIST data sets or
* provided by any other organization. The data sets are known good values,
* verified with two different JCE providers (solaris-sparcv9 ucrypto and
* linux SunJCE).
*
* Lengths around 64k are chosen because 64k is the point where
* com.sun.crypto.provider.GaloisCounterMode#doLastBlock() starts it's
* intrinsic warmup
*
* Plaintext is all zeros. Preset key and IV.
*
* The choice of MD5 is for speed. Shortcoming of the algorithm are
* not relevant for this test.
*/
public class GCMLargeDataKAT {
// Hash of encrypted results of AES/GCM for particular lengths.
// <data size, hash>
static final HashMap<Integer, String> results = new HashMap<>() {{
put(65534, "1397b91c31ce793895edace4e175bfee"); //64k-2
put(65535, "4ad101c9f450e686668b3f8f05db96f0"); //64k-1
put(65536, "fbfaee3451acd3f603200d6be0f39b24"); //64k
put(65537, "e7dfca4a71495c65d20982c3c9b9813f"); //64k+1
put(67583, "c8ebdcb3532ec6c165de961341af7635"); //66k-1
put(67584, "36559d108dfd25dd29da3fec3455b9e5"); //66k
put(67585, "1d21b42d80ea179810744fc23dc228b6"); //66k+1
put(102400, "0d1544fcab20bbd4c8103b9d273f2c82"); //100k
put(102401, "f2d53ef65fd12d0a861368659b23ea2e"); //100k+1
put(102402, "97f0f524cf63d2d9d23d81e64d416ee0"); //100k+2
put(102403, "4a6b4af55b7d9016b64114d6813d639c"); //100k+3
put(102404, "ba63cc131fcde2f12ddf2ac634201be8"); //100k+4
put(102405, "673d05c7fe5e283e42e5c0d049fdcea6"); //100k+5
put(102406, "76cc99a7850ce857eb3cb43049cf9877"); //100k+6
put(102407, "65863f99072cf2eb7fce18bd78b33f4e"); //100k+7
put(102408, "b9184f0f272682cc1f791fa7070eddd4"); //100k+8
put(102409, "45fe36afef43cc665bf22a9ca200c3c2"); //100k+9
put(102410, "67249e41646edcb37a78a61b0743cf11"); //100k+0
put(102411, "ffdc611e29c8849842e81ec78f32c415"); //100k+11
put(102412, "b7fde7fd52221057dccc1c181a140125"); //100k+12
put(102413, "4b1d6c64d56448105e5613157e69c0ae"); //100k+13
put(102414, "6d2c0b26c0c8785c8eec3298a5f0080c"); //100k+14
put(102415, "1df2061b114fbe56bdf3717e3ee61ef9"); //100k+15
put(102416, "a691742692c683ac9d1254df5fc5f768"); //100k+16
}};
static final int HIGHLEN = 102416;
static final int GCM_TAG_LENGTH = 16;
static final byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
static final byte[] key_code = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
static final GCMParameterSpec spec =
new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
static final SecretKey key = new SecretKeySpec(key_code, "AES");
static boolean testresult = true;
static byte[] plaintext = new byte[HIGHLEN];
static MessageDigest md5;
Cipher cipher;
GCMLargeDataKAT() {
}
byte[] encrypt(int inLen) {
try {
cipher = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
return cipher.doFinal(plaintext, 0, inLen);
} catch (Exception e) {
System.err.println("Encrypt Failure (length = " + inLen + ") : " +
e.getMessage());
e.printStackTrace();
}
return new byte[0];
}
static byte[] hash(byte[] data) {
return md5.digest(data);
}
// Decrypt the data and return a boolean if the plaintext is all 0's.
boolean decrypt(byte[] data) {
byte[] result = null;
int len = data.length - GCM_TAG_LENGTH;
if (data.length == 0) {
return false;
}
try {
cipher = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
cipher.init(Cipher.DECRYPT_MODE, key, spec);
result = cipher.doFinal(data);
} catch (Exception e) {
System.err.println("Decrypt Failure (length = " + len + ") : " +
e.getMessage());
e.printStackTrace();
return false;
}
if (result.length != len) {
System.err.println("Decrypt Failure (length = " + len +
") : plaintext length invalid = " + result.length);
}
// Return false if we find a non zero.
int i = 0;
while (result.length > i) {
if (result[i++] != 0) {
System.err.println("Decrypt Failure (length = " + len +
") : plaintext invalid, char index " + i);
return false;
}
}
return true;
}
void test() throws Exception {
// results order is not important
for (int l : results.keySet()) {
byte[] enc = new GCMLargeDataKAT().encrypt(l);
// verify hash with stored hash of that length
String hashstr = toHex(hash(enc));
boolean r = (hashstr.compareTo(results.get(l)) == 0);
System.out.println("---------------------------------------------");
// Encrypted test & results
System.out.println("Encrypt data size " + l + " \tResult: " +
(r ? "Pass" : "Fail"));
if (!r) {
if (enc.length != 0) {
System.out.println("\tExpected: " + results.get(l));
System.out.println("\tReturned: " + hashstr);
}
testresult = false;
continue;
}
// Decrypted test & results
r = decrypt(enc);
System.out.println("Decrypt data size " + l + " \tResult: " +
(r ? "Pass" : "Fail"));
if (!r) {
testresult = false;
}
}
// After test complete, throw an error if there was a failure
if (!testresult) {
throw new Exception("Tests failed");
}
}
/**
* With no argument, the test will run the predefined data lengths
*
* With an integer argument, this test will print the hash of the encrypted
* data of that integer length.
*
*/
public static void main(String args[]) throws Exception {
md5 = MessageDigest.getInstance("MD5");
if (args.length > 0) {
int len = Integer.parseInt(args[0]);
byte[] e = new GCMLargeDataKAT().encrypt(len);
System.out.println(toHex(hash(e)));
return;
}
new GCMLargeDataKAT().test();
}
// bytes to hex string
static String toHex(byte[] bytes) {
StringBuffer hexStringBuffer = new StringBuffer(32);
for (int i = 0; i < bytes.length; i++) {
hexStringBuffer.append(byteToHex(bytes[i]));
}
return hexStringBuffer.toString();
}
// byte to hex
static String byteToHex(byte num) {
char[] hexDigits = new char[2];
hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16);
hexDigits[1] = Character.forDigit((num & 0xF), 16);
return new String(hexDigits);
}
}

View file

@ -0,0 +1,220 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.GCMParameterSpec;
/*
* @test
* @bug 8048596
* @summary Check if GCMParameterSpec works as expected
*/
public class GCMParameterSpecTest {
private static final int[] IV_LENGTHS = { 96, 8, 1024 };
private static final int[] KEY_LENGTHS = { 128, 192, 256 };
private static final int[] DATA_LENGTHS = { 0, 128, 1024 };
private static final int[] AAD_LENGTHS = { 0, 128, 1024 };
private static final int[] TAG_LENGTHS = { 128, 120, 112, 104, 96 };
private static final int[] OFFSETS = { 0, 2, 5, 99 };
private static final String TRANSFORMATION = "AES/GCM/NoPadding";
private static final String TEMPLATE = "Test:\n tag = %d\n"
+ " IV length = %d\n data length = %d\n"
+ " AAD length = %d\n offset = %d\n keylength = %d\n";
private final byte[] IV;
private final byte[] IVO;
private final byte[] data;
private final byte[] AAD;
private final SecretKey key;
private final int tagLength;
private final int IVlength;
private final int offset;
/**
* Initialize IV, IV with offset, plain text, AAD and SecretKey
*
* @param keyLength length of a secret key
* @param tagLength tag length
* @param IVlength IV length
* @param offset offset in a buffer for IV
* @param textLength plain text length
* @param AADLength AAD length
*/
public GCMParameterSpecTest(int keyLength, int tagLength, int IVlength,
int offset, int textLength, int AADLength)
throws NoSuchAlgorithmException, NoSuchProviderException {
this.tagLength = tagLength; // save tag length
this.IVlength = IVlength; // save IV length
this.offset = offset; // save IV offset
// prepare IV
IV = Helper.generateBytes(IVlength);
// prepare IV with offset
IVO = new byte[this.IVlength + this.offset];
System.arraycopy(IV, 0, IVO, offset, this.IVlength);
// prepare data
data = Helper.generateBytes(textLength);
// prepare AAD
AAD = Helper.generateBytes(AADLength);
// init a secret key
KeyGenerator kg = KeyGenerator.getInstance("AES",
System.getProperty("test.provider.name", "SunJCE"));
kg.init(keyLength);
key = kg.generateKey();
}
/*
* Run the test for each key length, tag length, IV length, plain text
* length, AAD length and offset.
*/
public static void main(String[] args) throws Exception {
boolean success = true;
for (int k : KEY_LENGTHS) {
if (k > Cipher.getMaxAllowedKeyLength(TRANSFORMATION)) {
// skip this if this key length is larger than what's
// allowed in the jce jurisdiction policy files
continue;
}
for (int t : TAG_LENGTHS) {
for (int n : IV_LENGTHS) {
for (int p : DATA_LENGTHS) {
for (int a : AAD_LENGTHS) {
for (int o : OFFSETS) {
System.out.printf(TEMPLATE, t, n, p, a, o, k);
success &= new GCMParameterSpecTest(
k, t, n, o, p, a).doTest();
}
}
}
}
}
}
if (!success) {
throw new RuntimeException("At least one test case failed");
}
}
/*
* Run the test:
* - check if result of encryption of plain text is the same
* when parameters constructed with different GCMParameterSpec
* constructors are used
* - check if GCMParameterSpec.getTLen() is equal to actual tag length
* - check if ciphertext has the same length as plaintext
*/
private boolean doTest() throws Exception {
GCMParameterSpec spec1 = new GCMParameterSpec(tagLength, IV);
GCMParameterSpec spec2 = new GCMParameterSpec(tagLength, IVO, offset,
IVlength);
byte[] cipherText1 = getCipherTextBySpec(spec1);
if (cipherText1 == null) {
return false;
}
byte[] cipherText2 = getCipherTextBySpec(spec2);
if (cipherText2 == null) {
return false;
}
if (!Arrays.equals(cipherText1, cipherText2)) {
System.out.println("Cipher texts are different");
return false;
}
if (spec1.getTLen() != spec2.getTLen()) {
System.out.println("Tag lengths are not equal");
return false;
}
byte[] recoveredText1 = recoverCipherText(cipherText1, spec2);
if (recoveredText1 == null) {
return false;
}
byte[] recoveredText2 = recoverCipherText(cipherText2, spec1);
if (recoveredText2 == null) {
return false;
}
if (!Arrays.equals(recoveredText1, recoveredText2)) {
System.out.println("Recovered texts are different");
return false;
}
if (!Arrays.equals(recoveredText1, data)) {
System.out.println("Recovered and original texts are not equal");
return false;
}
return true;
}
/*
* Encrypt a plain text, and check if GCMParameterSpec.getIV()
* is equal to Cipher.getIV()
*/
private byte[] getCipherTextBySpec(GCMParameterSpec spec) throws Exception {
// init a cipher
Cipher cipher = createCipher(Cipher.ENCRYPT_MODE, spec);
cipher.updateAAD(AAD);
byte[] cipherText = cipher.doFinal(data);
// check IVs
if (!Arrays.equals(cipher.getIV(), spec.getIV())) {
System.out.println("IV in parameters is incorrect");
return null;
}
if (spec.getTLen() != (cipherText.length - data.length) * 8) {
System.out.println("Tag length is incorrect");
return null;
}
return cipherText;
}
private byte[] recoverCipherText(byte[] cipherText, GCMParameterSpec spec)
throws Exception {
// init a cipher
Cipher cipher = createCipher(Cipher.DECRYPT_MODE, spec);
// check IVs
if (!Arrays.equals(cipher.getIV(), spec.getIV())) {
System.out.println("IV in parameters is incorrect");
return null;
}
cipher.updateAAD(AAD);
return cipher.doFinal(cipherText);
}
private Cipher createCipher(int mode, GCMParameterSpec spec)
throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION,
System.getProperty("test.provider.name", "SunJCE"));
cipher.init(mode, key, spec);
return cipher;
}
}

View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 2021, 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.
*
* 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.
*/
import javax.crypto.Cipher;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HexFormat;
/*
* @test
* @summary Call decrypt doFinal() with different output values to see if the
* the operation can complete after a ShortBufferException
*/
public class GCMShortBuffer {
static Cipher c;
static final GCMParameterSpec iv = new GCMParameterSpec(128, new byte[16]);
static final SecretKeySpec keySpec = new SecretKeySpec(new byte[16], "AES");
static byte cipherText[], plaintext[] = new byte[51];
boolean error = false;
GCMShortBuffer(byte[] out) throws Exception {
int len = cipherText.length - 1;
c.init(Cipher.DECRYPT_MODE, keySpec, iv);
byte[] pt = new byte[c.getOutputSize(cipherText.length)];
c.update(cipherText, 0, 1);
try {
c.doFinal(cipherText, 1, len, out, 0);
} catch (ShortBufferException e) {
System.out.println("ShortBuffer caught");
} catch (Exception e) {
throw e;
}
int r = c.doFinal(cipherText, 1, len, pt, 0);
if (r != pt.length) {
System.out.println(
"doFinal() return ( " + r + ") is not the same " +
"as getOutputSize returned" + pt.length);
error = true;
}
if (Arrays.compare(pt, plaintext) != 0) {
System.out.println("output : " + HexFormat.of().formatHex(pt));
System.out.println("expected: " +
HexFormat.of().formatHex(plaintext));
System.out.println("output and plaintext do not match");
error = true;
}
if (error) {
throw new Exception("An error has occurred");
}
}
GCMShortBuffer(ByteBuffer dst) throws Exception {
int len = cipherText.length - 1;
ByteBuffer out = ByteBuffer.allocate(plaintext.length);
c.init(Cipher.DECRYPT_MODE, keySpec, iv);
c.update(cipherText, 0, 1);
ByteBuffer ct = ByteBuffer.wrap(cipherText, 1, len);
try {
c.doFinal(ct , dst);
} catch (ShortBufferException e) {
System.out.println("ShortBuffer caught");
} catch (Exception e) {
throw e;
}
int r = c.doFinal(ByteBuffer.wrap(cipherText, 1, len), out);
out.flip();
if (r != out.capacity()) {
System.out.println(
"doFinal() return ( " + r + ") is not the same" +
" as getOutputSize returned" + out.capacity());
error = true;
}
if (out.compareTo(ByteBuffer.wrap(plaintext)) != 0) {
System.out.println("output and plaintext do not match");
System.out.println("output : " +
HexFormat.of().formatHex(out.array()));
System.out.println("expected: " +
HexFormat.of().formatHex(plaintext));
error = true;
}
if (error) {
throw new Exception("An error has occurred");
}
}
public static void main(String args[]) throws Exception {
c = Cipher.getInstance("AES/GCM/NoPadding");
c.init(Cipher.ENCRYPT_MODE, keySpec, iv);
cipherText = c.doFinal(plaintext);
new GCMShortBuffer(new byte[13]);
new GCMShortBuffer(new byte[50]);
new GCMShortBuffer(ByteBuffer.allocate(13));
new GCMShortBuffer(ByteBuffer.allocate(50));
}
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2023, Alphabet LLC. 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.
*
* 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.
*/
/*
* @test
* @bug 8314045
* @summary ArithmeticException in GaloisCounterMode
*/
import java.nio.ByteBuffer;
import javax.crypto.AEADBadTagException;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class GCMShortInput {
public static void main(String args[]) throws Exception {
SecretKeySpec keySpec =
new SecretKeySpec(
new byte[] {
88, 26, 43, -100, -24, -29, -70, 10, 34, -85, 52, 101, 45, -68, -105,
-123
},
"AES");
GCMParameterSpec params =
new GCMParameterSpec(8 * 16, new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, params);
try {
cipher.doFinal(ByteBuffer.allocate(0), ByteBuffer.allocate(0));
throw new AssertionError("AEADBadTagException expected");
} catch (AEADBadTagException e) {
// expected
}
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2015, 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.
*
* 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.
*/
public class Helper {
public static byte[] generateBytes(int length) {
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++) {
bytes[i] = (byte) (i % 256);
}
return bytes;
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.security.AlgorithmParameters;
import java.security.Key;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
/*
* @test
* @bug 8048596
* @summary Check if a key wrapper works properly with GCM mode
*/
public class KeyWrapper {
static final String AES = "AES";
static final String TRANSFORMATION = "AES/GCM/NoPadding";
static final String PROVIDER = System.getProperty("test.provider.name", "SunJCE");
static final int KEY_LENGTH = 128;
public static void main(String argv[]) throws Exception {
doTest(PROVIDER, TRANSFORMATION);
}
private static void doTest(String provider, String algo) throws Exception {
SecretKey key;
SecretKey keyToWrap;
// init a secret Key
KeyGenerator kg = KeyGenerator.getInstance(AES, PROVIDER);
kg.init(KEY_LENGTH);
key = kg.generateKey();
keyToWrap = kg.generateKey();
// initialization
Cipher cipher = Cipher.getInstance(algo, provider);
cipher.init(Cipher.WRAP_MODE, key);
AlgorithmParameters params = cipher.getParameters();
// wrap the key
byte[] keyWrapper = cipher.wrap(keyToWrap);
try {
// check if we can't wrap it again with the same key/IV
keyWrapper = cipher.wrap(keyToWrap);
throw new RuntimeException(
"FAILED: expected IllegalStateException hasn't "
+ "been thrown ");
} catch (IllegalStateException ise) {
System.out.println(ise.getMessage());
System.out.println("Expected exception");
}
// unwrap the key
cipher.init(Cipher.UNWRAP_MODE, key, params);
cipher.unwrap(keyWrapper, algo, Cipher.SECRET_KEY);
// check if we can unwrap second time
Key unwrapKey = cipher.unwrap(keyWrapper, algo, Cipher.SECRET_KEY);
if (!Arrays.equals(keyToWrap.getEncoded(), unwrapKey.getEncoded())) {
throw new RuntimeException(
"FAILED: original and unwrapped keys are not equal");
}
}
}

View file

@ -0,0 +1,182 @@
/*
* Copyright (c) 2020, 2024, 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.
*
* 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.
*/
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.security.spec.AlgorithmParameterSpec;
/*
* @test
* @summary This tests overlapping buffers using ByteBuffer.slice() with
* array-backed ByteBuffer, read only array-backed, ByteBuffer, and direct
* ByteBuffer.
* @run main OverlapByteBuffer AES/GCM/NoPadding
* @run main OverlapByteBuffer ChaCha20-Poly1305
*/
/*
* This tests overlapping buffers created with ByteBuffer.slice(). That is
* when the input and output ByteBuffers have shared memory (use the same
* underlying buffer space, commonly used for in-place crypto). The
* complication is the Cipher object specifies that it must be copy-safe. That
* means the output buffer will not overwrite any input data that has not been
* processed. If the output buffer's position or offset is greater than the
* input's overwriting will occur.
*/
public class OverlapByteBuffer {
byte[] baseBuf = new byte[8192];
ByteBuffer output, input, in;
int outOfs;
String algorithm;
SecretKeySpec key;
AlgorithmParameterSpec params;
public static void main(String[] args) throws Exception {
new OverlapByteBuffer(args[0]).test();
}
OverlapByteBuffer(String algorithm) throws Exception {
this.algorithm = algorithm;
switch (algorithm) {
case "AES/GCM/NoPadding" -> {
params = new GCMParameterSpec(128, new byte[12]);
key = new SecretKeySpec(new byte[16], "AES");
}
case "ChaCha20-Poly1305" -> {
params = new IvParameterSpec(new byte[12]);
key = new SecretKeySpec(new byte[32], "");
}
default -> throw new Exception("unknown algorithm: " + algorithm);
}
}
void test() throws Exception {
// Output offset from the baseBuf
for (int i = 0; i < 3; i++) {
for (outOfs = -1; outOfs <= 1; outOfs++) {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, params);
// Offset on the particular ByteBuffer (aka position())
int inOfsInBuf = 1;
int outOfsInBuf = inOfsInBuf + outOfs;
int sliceLen = cipher.getOutputSize(baseBuf.length);
int bufferSize = sliceLen + Math.max(inOfsInBuf, outOfsInBuf);
byte[] buffer;
// Create overlapping input and output buffers
switch (i) {
case 0 -> {
buffer = new byte[bufferSize];
output = ByteBuffer.wrap(buffer, outOfsInBuf, sliceLen).
slice();
input = ByteBuffer.wrap(buffer, inOfsInBuf, sliceLen).
slice();
System.out.println("Using array-backed ByteBuffer");
in = input.duplicate();
}
case 1 -> {
buffer = new byte[bufferSize];
output = ByteBuffer.wrap(buffer, outOfsInBuf, sliceLen).
slice();
input = ByteBuffer.wrap(buffer, inOfsInBuf, sliceLen).
slice();
System.out.println("Using read-only array-backed " +
"ByteBuffer");
in = input.asReadOnlyBuffer();
}
case 2 -> {
System.out.println("Using direct ByteBuffer");
ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize);
output = buf.duplicate();
output.position(outOfsInBuf);
output.limit(sliceLen + outOfsInBuf);
output = output.slice();
input = buf.duplicate();
input.position(inOfsInBuf);
input.limit(sliceLen + inOfsInBuf);
input = input.slice();
in = input.duplicate();
}
default -> throw new Exception("Unknown index " + i);
}
System.out.println("inOfsInBuf = " + inOfsInBuf);
System.out.println("outOfsInBuf = " + outOfsInBuf);
// Copy data into shared buffer
input.put(baseBuf);
input.flip();
in.limit(input.limit());
try {
int ctSize = cipher.doFinal(in, output);
// Get ready to decrypt
byte[] tmp = new byte[ctSize];
output.flip();
output.get(tmp);
output.clear();
input.clear();
input.put(tmp);
input.flip();
in.clear();
in.limit(input.limit());
cipher.init(Cipher.DECRYPT_MODE, key, params);
cipher.doFinal(in, output);
output.flip();
ByteBuffer b = ByteBuffer.wrap(baseBuf);
if (b.compareTo(output) != 0) {
System.err.println(
"\nresult (" + output + "):\n" +
byteToHex(output) +
"\nexpected (" + b + "):\n" +
byteToHex(b));
throw new Exception("Mismatch");
}
} catch (Exception e) {
throw new Exception("Error with base offset " + outOfs, e);
}
}
}
}
private static String byteToHex(ByteBuffer bb) {
StringBuilder s = new StringBuilder();
while (bb.remaining() > 0) {
s.append(String.format("%02x", bb.get()));
}
return s.toString();
}
}

View file

@ -0,0 +1,317 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/*
* @test
* @bug 8048596
* @summary Test CICO AEAD read/write/skip operations
*/
public class ReadWriteSkip {
static enum BufferType {
BYTE_ARRAY_BUFFERING, INT_BYTE_BUFFERING
}
static final int KEY_LENGTHS[] = {128, 192, 256};
static final int TXT_LENGTHS[] = {800, 0};
static final int AAD_LENGTHS[] = {0, 100};
static final int BLOCK = 50;
static final int SAVE = 45;
static final int DISCARD = BLOCK - SAVE;
static final String PROVIDER = System.getProperty("test.provider.name", "SunJCE");
static final String AES = "AES";
static final String GCM = "GCM";
static final String PADDING = "NoPadding";
static final String TRANSFORM = AES + "/" + GCM + "/" + PADDING;
final SecretKey key;
final byte[] plaintext;
final byte[] AAD;
final int textLength;;
final int keyLength;
Cipher encryptCipher;
Cipher decryptCipher;
CipherInputStream ciInput;
public static void main(String[] args) throws Exception {
boolean success = true;
for (int keyLength : KEY_LENGTHS) {
if (keyLength > Cipher.getMaxAllowedKeyLength(TRANSFORM)) {
// skip this if this key length is larger than what's
// configured in the jce jurisdiction policy files
continue;
}
for (int textLength : TXT_LENGTHS) {
for (int AADLength : AAD_LENGTHS) {
System.out.println("Key length = " + keyLength
+ ", text length = " + textLength
+ ", AAD length = " + AADLength);
try {
run(keyLength, textLength, AADLength);
System.out.println("Test case passed");
} catch (Exception e) {
System.out.println("Test case failed: " + e);
success = false;
}
}
}
}
if (!success) {
throw new RuntimeException("At least one test case failed");
}
System.out.println("Test passed");
}
ReadWriteSkip(int keyLength, int textLength, int AADLength)
throws Exception {
this.keyLength = keyLength;
this.textLength = textLength;
// init AAD
this.AAD = Helper.generateBytes(AADLength);
// init a secret Key
KeyGenerator kg = KeyGenerator.getInstance(AES, PROVIDER);
kg.init(this.keyLength);
this.key = kg.generateKey();
this.plaintext = Helper.generateBytes(textLength);
}
final void doTest(BufferType type) throws Exception {
// init ciphers
encryptCipher = createCipher(Cipher.ENCRYPT_MODE);
decryptCipher = createCipher(Cipher.DECRYPT_MODE);
// init cipher input stream
ciInput = new CipherInputStream(new ByteArrayInputStream(plaintext),
encryptCipher);
runTest(type);
}
void runTest(BufferType type) throws Exception {}
private Cipher createCipher(int mode) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(TRANSFORM, PROVIDER);
if (mode == Cipher.ENCRYPT_MODE) {
cipher.init(Cipher.ENCRYPT_MODE, key);
} else {
if (encryptCipher != null) {
cipher.init(Cipher.DECRYPT_MODE, key,
encryptCipher.getParameters());
} else {
throw new RuntimeException("Can't create a cipher");
}
}
cipher.updateAAD(AAD);
return cipher;
}
/*
* Run test cases
*/
static void run(int keyLength, int textLength, int AADLength)
throws Exception {
new ReadWriteTest(keyLength, textLength, AADLength)
.doTest(BufferType.BYTE_ARRAY_BUFFERING);
new ReadWriteTest(keyLength, textLength, AADLength)
.doTest(BufferType.INT_BYTE_BUFFERING);
new SkipTest(keyLength, textLength, AADLength)
.doTest(BufferType.BYTE_ARRAY_BUFFERING);
new SkipTest(keyLength, textLength, AADLength)
.doTest(BufferType.INT_BYTE_BUFFERING);
}
static void check(byte[] first, byte[] second) {
if (!Arrays.equals(first, second)) {
throw new RuntimeException("Arrays are not equal");
}
}
/*
* CICO AEAD read/write functional test.
*
* Check if encrypt/decrypt operations work correctly.
*
* Test scenario:
* - initializes plain text
* - for given AEAD algorithm instantiates encrypt and decrypt Ciphers
* - instantiates CipherInputStream with the encrypt Cipher
* - instantiates CipherOutputStream with the decrypt Cipher
* - performs reading from the CipherInputStream (encryption data)
* and writing to the CipherOutputStream (decryption). As a result,
* output of the CipherOutputStream should be equal
* with original plain text
* - check if the original plain text is equal to output
* of the CipherOutputStream
* - if it is equal the test passes, otherwise it fails
*/
static class ReadWriteTest extends ReadWriteSkip {
public ReadWriteTest(int keyLength, int textLength, int AADLength)
throws Exception {
super(keyLength, textLength, AADLength);
}
@Override
public void runTest(BufferType bufType) throws IOException,
GeneralSecurityException {
ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
try (CipherOutputStream ciOutput = new CipherOutputStream(baOutput,
decryptCipher)) {
if (bufType == BufferType.BYTE_ARRAY_BUFFERING) {
doByteTest(ciOutput);
} else {
doIntTest(ciOutput);
}
}
check(plaintext, baOutput.toByteArray());
}
/*
* Implements byte array buffering type test case
*/
public void doByteTest(CipherOutputStream out) throws IOException {
byte[] buffer = Helper.generateBytes(textLength + 1);
int len = ciInput.read(buffer);
while (len != -1) {
out.write(buffer, 0, len);
len = ciInput.read(buffer);
}
}
/*
* Implements integer buffering type test case
*/
public void doIntTest(CipherOutputStream out) throws IOException {
int buffer = ciInput.read();
while (buffer != -1) {
out.write(buffer);
buffer = ciInput.read();
}
}
}
/*
* CICO AEAD SKIP functional test.
*
* Checks if the encrypt/decrypt operations work correctly
* when skip() method is used.
*
* Test scenario:
* - initializes a plain text
* - initializes ciphers
* - initializes cipher streams
* - split plain text to TEXT_SIZE/BLOCK blocks
* - read from CipherInputStream2 one block at time
* - the last DISCARD = BLOCK - SAVE bytes are skipping for each block
* - therefore, plain text data go through CipherInputStream1 (encrypting)
* and CipherInputStream2 (decrypting)
* - as a result, output should equal to the original text
* except DISCART byte for each block
* - check result buffers
*/
static class SkipTest extends ReadWriteSkip {
private final int numberOfBlocks;
private final byte[] outputText;
public SkipTest(int keyLength, int textLength, int AADLength)
throws Exception {
super(keyLength, textLength, AADLength);
numberOfBlocks = this.textLength / BLOCK;
outputText = new byte[numberOfBlocks * SAVE];
}
private void doByteTest(int blockNum, CipherInputStream cis)
throws IOException {
int index = blockNum * SAVE;
int len = cis.read(outputText, index, SAVE);
index += len;
int read = 0;
while (len != SAVE && read != -1) {
read = cis.read(outputText, index, SAVE - len);
len += read;
index += read;
}
}
private void doIntTest(int blockNum, CipherInputStream cis)
throws IOException {
int i = blockNum * SAVE;
for (int j = 0; j < SAVE && i < outputText.length; j++, i++) {
int b = cis.read();
if (b != -1) {
outputText[i] = (byte) b;
}
}
}
@Override
public void runTest(BufferType type) throws IOException,
NoSuchAlgorithmException {
try (CipherInputStream cis = new CipherInputStream(ciInput,
decryptCipher)) {
for (int i = 0; i < numberOfBlocks; i++) {
if (type == BufferType.BYTE_ARRAY_BUFFERING) {
doByteTest(i, cis);
} else {
doIntTest(i, cis);
}
if (cis.available() >= DISCARD) {
cis.skip(DISCARD);
} else {
for (int k = 0; k < DISCARD; k++) {
cis.read();
}
}
}
}
byte[] expectedText = new byte[numberOfBlocks * SAVE];
for (int m = 0; m < numberOfBlocks; m++) {
for (int n = 0; n < SAVE; n++) {
expectedText[m * SAVE + n] = plaintext[m * BLOCK + n];
}
}
check(expectedText, outputText);
}
}
}

View file

@ -0,0 +1,435 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.Provider;
import java.security.Security;
import java.util.HexFormat;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.GCMParameterSpec;
import jdk.test.lib.Convert;
/*
* @test
* @bug 8048596
* @summary Check if AEAD operations work correctly when buffers used
* for storing plain text and cipher text are overlapped or the same
* @library /test/lib
*/
public class SameBuffer {
private static final String PROVIDER = System.getProperty("test.provider.name", "SunJCE");
private static final String AES = "AES";
private static final String GCM = "GCM";
private static final String PADDING = "NoPadding";
private static final int OFFSET = 2;
private static final int OFFSETS = 4;
private static final int KEY_LENGTHS[] = { 128, 192, 256 };
private static final int TEXT_LENGTHS[] = { 0, 1024 };
private static final int AAD_LENGTHS[] = { 0, 1024 };
private final Provider provider;
private final SecretKey key;
private final String transformation;
private final int textLength;
private final int AADLength;
/**
* Constructor of the test
*
* @param provider security provider
* @param keyStrength key length
* @param textLength length of data
* @param AADLength AAD length
*/
public SameBuffer(Provider provider, String algorithm, String mode,
String padding, int keyStrength, int textLength, int AADLength)
throws Exception {
// init a secret key
KeyGenerator kg = KeyGenerator.getInstance(algorithm, provider);
kg.init(keyStrength);
key = kg.generateKey();
this.transformation = algorithm + "/" + mode + "/" + padding;
this.provider = provider;
this.textLength = textLength;
this.AADLength = AADLength;
}
public static void main(String[] args) throws Exception {
Provider p = Security.getProvider(PROVIDER);
for (int keyLength : KEY_LENGTHS) {
for (int textLength : TEXT_LENGTHS) {
for (int AADLength : AAD_LENGTHS) {
for (int i = 0; i < OFFSETS; i++) {
// try different offsets
int offset = i * OFFSET;
runTest(p, AES, GCM, PADDING, keyLength, textLength,
AADLength, offset);
}
}
}
}
}
/*
* Run single test case with given parameters
*/
static void runTest(Provider p, String algo, String mode,
String padding, int keyLength, int textLength, int AADLength,
int offset) throws Exception {
System.out.println("Testing " + keyLength + " key length; "
+ textLength + " text length; " + AADLength + " AAD length; "
+ offset + " offset");
if (keyLength > Cipher.getMaxAllowedKeyLength(algo)) {
// skip this if this key length is larger than what's
// configured in the jce jurisdiction policy files
return;
}
SameBuffer test = new SameBuffer(p, algo, mode,
padding, keyLength, textLength, AADLength);
/*
* There are four test cases:
* 1. AAD and text are placed in separated byte arrays
* 2. AAD and text are placed in the same byte array
* 3. AAD and text are placed in separated byte buffers
* 4. AAD and text are placed in the same byte buffer
*/
Cipher ci = test.createCipher(Cipher.ENCRYPT_MODE, null);
AlgorithmParameters params = ci.getParameters();
test.doTestWithSeparateArrays(offset, params);
test.doTestWithSameArrays(offset, params);
test.doTestWithSeparatedBuffer(offset, params);
test.doTestWithSameBuffer(offset, params);
}
/*
* Run the test in case when AAD and text are placed in separated byte
* arrays.
*/
private void doTestWithSeparateArrays(int offset,
AlgorithmParameters params) throws Exception {
// prepare buffers to test
Cipher c = createCipher(Cipher.ENCRYPT_MODE, params);
int outputLength = c.getOutputSize(textLength);
int outputBufSize = outputLength + offset * 2;
byte[] inputText = Helper.generateBytes(outputBufSize);
byte[] AAD = Helper.generateBytes(AADLength);
// do the test
runGCMWithSeparateArray(Cipher.ENCRYPT_MODE, AAD, inputText, offset * 2,
textLength, offset, params);
int tagLength = c.getParameters()
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
runGCMWithSeparateArray(Cipher.DECRYPT_MODE, AAD, inputText, offset,
textLength + tagLength, offset, params);
}
/**
* Run the test in case when AAD and text are placed in the same byte
* array.
*/
private void doTestWithSameArrays(int offset, AlgorithmParameters params)
throws Exception {
// prepare buffers to test
Cipher c = createCipher(Cipher.ENCRYPT_MODE, params);
int outputLength = c.getOutputSize(textLength);
int outputBufSize = AADLength + outputLength + offset * 2;
byte[] AAD_and_text = Helper.generateBytes(outputBufSize);
// do the test
runGCMWithSameArray(Cipher.ENCRYPT_MODE, AAD_and_text, AADLength + offset,
textLength, params);
int tagLength = c.getParameters()
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
runGCMWithSameArray(Cipher.DECRYPT_MODE, AAD_and_text, AADLength + offset,
textLength + tagLength, params);
}
/*
* Run the test in case when AAD and text are placed in separated ByteBuffer
*/
private void doTestWithSeparatedBuffer(int offset,
AlgorithmParameters params) throws Exception {
// prepare AAD byte buffers to test
byte[] AAD = Helper.generateBytes(AADLength);
ByteBuffer AAD_Buf = ByteBuffer.allocate(AADLength);
AAD_Buf.put(AAD, 0, AAD.length);
AAD_Buf.flip();
// prepare text byte buffer to encrypt/decrypt
Cipher c = createCipher(Cipher.ENCRYPT_MODE, params);
int outputLength = c.getOutputSize(textLength);
int outputBufSize = outputLength + offset;
byte[] inputText = Helper.generateBytes(outputBufSize);
ByteBuffer plainTextBB = ByteBuffer.allocateDirect(inputText.length);
plainTextBB.put(inputText);
plainTextBB.position(offset);
plainTextBB.limit(offset + textLength);
// do test
runGCMWithSeparateBuffers(Cipher.ENCRYPT_MODE, AAD_Buf, plainTextBB, offset,
textLength, params);
int tagLength = c.getParameters()
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
plainTextBB.position(offset);
plainTextBB.limit(offset + textLength + tagLength);
runGCMWithSeparateBuffers(Cipher.DECRYPT_MODE, AAD_Buf, plainTextBB, offset,
textLength + tagLength, params);
}
/*
* Run the test in case when AAD and text are placed in the same ByteBuffer
*/
private void doTestWithSameBuffer(int offset, AlgorithmParameters params)
throws Exception {
// calculate output length
Cipher c = createCipher(Cipher.ENCRYPT_MODE, params);
int outputLength = c.getOutputSize(textLength);
// prepare byte buffer contained AAD and plain text
int bufSize = AADLength + offset + outputLength;
byte[] AAD_and_Text = Helper.generateBytes(bufSize);
ByteBuffer AAD_and_Text_Buf = ByteBuffer.allocate(bufSize);
AAD_and_Text_Buf.put(AAD_and_Text, 0, AAD_and_Text.length);
// do test
runGCMWithSameBuffer(Cipher.ENCRYPT_MODE, AAD_and_Text_Buf, offset,
textLength, params);
int tagLength = c.getParameters()
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
AAD_and_Text_Buf.limit(AADLength + offset + textLength + tagLength);
runGCMWithSameBuffer(Cipher.DECRYPT_MODE, AAD_and_Text_Buf, offset,
textLength + tagLength, params);
}
/*
* Execute GCM encryption/decryption of a text placed in a byte array.
* AAD is placed in the separated byte array.
* Data are processed twice:
* - in a separately allocated buffer
* - in the text buffer
* Check if two results are equal
*/
private void runGCMWithSeparateArray(int mode, byte[] AAD, byte[] text,
int txtOffset, int length, int offset, AlgorithmParameters params)
throws Exception {
// first, generate the cipher text at an allocated buffer
Cipher cipher = createCipher(mode, params);
cipher.updateAAD(AAD);
byte[] outputText = cipher.doFinal(text, txtOffset, length);
// new cipher for encrypt operation
Cipher anotherCipher = createCipher(mode, params);
anotherCipher.updateAAD(AAD);
// next, generate cipher text again at the same buffer of plain text
int myoff = offset;
int off = anotherCipher.update(text, txtOffset, length, text, myoff);
anotherCipher.doFinal(text, myoff + off);
// check if two resutls are equal
if (!isEqual(text, myoff, outputText, 0, outputText.length)) {
System.err.println(
"\noutputText: len = " + outputText.length + " txtOffset = " + txtOffset + "\n" +
HexFormat.of().withUpperCase().formatHex(outputText) + "\n" +
"text: len = " + text.length + " myoff = " + myoff + "\n" +
HexFormat.of().withUpperCase().formatHex(text) + "\n" +
"length " + length);
System.err.println("tlen = " + params.getParameterSpec(GCMParameterSpec.class).getTLen() / 8);
throw new RuntimeException("Two results not equal, mode:" + mode);
}
}
/*
* Execute GCM encrption/decryption of a text. The AAD and text to process
* are placed in the same byte array. Data are processed twice:
* - in a separetly allocated buffer
* - in a buffer that shares content of the AAD_and_Text_BA
* Check if two results are equal
*/
private void runGCMWithSameArray(int mode, byte[] array, int txtOffset,
int length, AlgorithmParameters params) throws Exception {
// first, generate cipher text at an allocated buffer
Cipher cipher = createCipher(mode, params);
cipher.updateAAD(array, 0, AADLength);
byte[] outputText = cipher.doFinal(array, txtOffset, length);
// new cipher for encrypt operation
Cipher anotherCipher = createCipher(mode, params);
anotherCipher.updateAAD(array, 0, AADLength);
// next, generate cipher text again at the same buffer of plain text
int off = anotherCipher.update(array, txtOffset, length,
array, txtOffset);
anotherCipher.doFinal(array, txtOffset + off);
// check if two results are equal or not
if (!isEqual(array, txtOffset, outputText, 0,
outputText.length)) {
throw new RuntimeException(
"Two results are not equal, mode:" + mode);
}
}
/*
* Execute GCM encryption/decryption of textBB. AAD and text to process are
* placed in different byte buffers. Data are processed twice:
* - in a separately allocated buffer
* - in a buffer that shares content of the textBB
* Check if results are equal
*/
private void runGCMWithSeparateBuffers(int mode, ByteBuffer buffer,
ByteBuffer textBB, int txtOffset, int dataLength,
AlgorithmParameters params) throws Exception {
// take offset into account
textBB.position(txtOffset);
textBB.mark();
// first, generate the cipher text at an allocated buffer
Cipher cipher = createCipher(mode, params);
cipher.updateAAD(buffer);
buffer.flip();
ByteBuffer outBB = ByteBuffer.allocateDirect(
cipher.getOutputSize(dataLength));
cipher.doFinal(textBB, outBB);// get cipher text in outBB
outBB.flip();
// restore positions
textBB.reset();
// next, generate cipher text again in a buffer that shares content
Cipher anotherCipher = createCipher(mode, params);
anotherCipher.updateAAD(buffer);
buffer.flip();
ByteBuffer buf2 = textBB.duplicate(); // buf2 shares textBuf context
buf2.limit(txtOffset + anotherCipher.getOutputSize(dataLength));
int dataProcessed2 = anotherCipher.doFinal(textBB, buf2);
buf2.position(txtOffset);
buf2.limit(txtOffset + dataProcessed2);
if (!buf2.equals(outBB)) {
throw new RuntimeException(
"Two results are not equal, mode:" + mode);
}
}
/*
* Execute GCM encryption/decryption of text. AAD and a text to process are
* placed in the same buffer. Data is processed twice:
* - in a separately allocated buffer
* - in a buffer that shares content of the AAD_and_Text_BB
*/
private void runGCMWithSameBuffer(int mode, ByteBuffer buffer,
int txtOffset, int length, AlgorithmParameters params)
throws Exception {
// allocate a separate buffer
Cipher cipher = createCipher(mode, params);
ByteBuffer outBB = ByteBuffer.allocateDirect(
cipher.getOutputSize(length));
// first, generate the cipher text at an allocated buffer
buffer.flip();
buffer.limit(AADLength);
cipher.updateAAD(buffer);
buffer.limit(AADLength + txtOffset + length);
buffer.position(AADLength + txtOffset);
cipher.doFinal(buffer, outBB);
outBB.flip(); // cipher text in outBB
// next, generate cipherText again in the same buffer
Cipher anotherCipher = createCipher(mode, params);
buffer.flip();
buffer.limit(AADLength);
anotherCipher.updateAAD(buffer);
buffer.limit(AADLength + txtOffset + length);
buffer.position(AADLength + txtOffset);
// share textBuf context
ByteBuffer buf2 = buffer.duplicate();
buf2.limit(AADLength + txtOffset + anotherCipher.getOutputSize(length));
int dataProcessed2 = anotherCipher.doFinal(buffer, buf2);
buf2.position(AADLength + txtOffset);
buf2.limit(AADLength + txtOffset + dataProcessed2);
if (!buf2.equals(outBB)) {
throw new RuntimeException(
"Two results are not equal, mode:" + mode);
}
}
private boolean isEqual(byte[] A, int offsetA, byte[] B, int offsetB,
int bytesToCompare) {
System.out.println("offsetA: " + offsetA + " offsetB: " + offsetA
+ " bytesToCompare: " + bytesToCompare);
for (int i = 0; i < bytesToCompare; i++) {
int setA = i + offsetA;
int setB = i + offsetB;
if (setA > A.length - 1 || setB > B.length - 1
|| A[setA] != B[setB]) {
System.err.println("i = " + i + " A[setA] = " + A[setA] +
" B[setB] = " + B[setB]);
return false;
}
}
return true;
}
/*
* Creates a Cipher object for testing: for encryption it creates new Cipher
* based on previously saved parameters (it is prohibited to use the same
* Cipher twice for encription during GCM mode), or returns initiated
* existing Cipher.
*/
private Cipher createCipher(int mode, AlgorithmParameters params)
throws Exception {
Cipher cipher = Cipher.getInstance(transformation, provider);
if (Cipher.ENCRYPT_MODE == mode) {
// initiate it with the saved parameters
if (params != null) {
cipher.init(Cipher.ENCRYPT_MODE, key, params);
} else {
// intiate the cipher and save parameters
cipher.init(Cipher.ENCRYPT_MODE, key);
}
} else if (cipher != null) {
cipher.init(Cipher.DECRYPT_MODE, key, params);
} else {
throw new RuntimeException("Can't create cipher");
}
return cipher;
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.security.AlgorithmParameters;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SealedObject;
/*
* @test
* @bug 8048596
* @summary Check if the seal/unseal feature works properly in AEAD/GCM mode.
*/
public class SealedObjectTest {
private static final String AES = "AES";
private static final String TRANSFORMATION = "AES/GCM/NoPadding";
private static final String PROVIDER = System.getProperty("test.provider.name", "SunJCE");
private static final int KEY_LENGTH = 128;
public static void main(String[] args) throws Exception {
doTest();
}
/*
* Run the test:
* - init a cipher with AES/GCM/NoPadding transformation
* - seal an object
* - check if we can't seal it again with the same key/IV
* - unseal the object using different methods of SealedObject class
* - check if the original and sealed objects are equal
*/
static void doTest() throws Exception {
// init a secret Key
KeyGenerator kg = KeyGenerator.getInstance(AES, PROVIDER);
kg.init(KEY_LENGTH);
SecretKey key = kg.generateKey();
// initialization
Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
cipher.init(Cipher.ENCRYPT_MODE, key);
AlgorithmParameters params = cipher.getParameters();
// seal an object
SealedObject so = new SealedObject(key, cipher);
try {
// check if we can't seal it again with the same key/IV
so = new SealedObject(key, cipher);
throw new RuntimeException(
"FAILED: expected IllegalStateException hasn't "
+ "been thrown");
} catch (IllegalStateException ise) {
System.out.println("Expected exception when seal it again with"
+ " the same key/IV: " + ise);
}
// unseal the object using getObject(Cipher) and compare
cipher.init(Cipher.DECRYPT_MODE, key, params);
SecretKey unsealedKey = (SecretKey) so.getObject(cipher);
assertKeysSame(unsealedKey, key, "SealedObject.getObject(Cipher)");
// unseal the object using getObject(Key) and compare
unsealedKey = (SecretKey) so.getObject(key);
assertKeysSame(unsealedKey, key, "SealedObject.getObject(Key)");
// unseal the object using getObject(Key, String) and compare
unsealedKey = (SecretKey) so.getObject(key, PROVIDER);
assertKeysSame(unsealedKey, key,
"SealedObject.getObject(Key, String)");
}
/**
* Compare two SecretKey objects.
*
* @param key1 first key
* @param key2 second key
* @param meth method that was used for unsealing the SecretKey object
* @return true if key1 and key2 are the same, false otherwise.
*/
static void assertKeysSame(SecretKey key1, SecretKey key2, String meth) {
if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) {
throw new RuntimeException(
"FAILED: original and unsealed objects aren't the same for "
+ meth);
}
}
}

View file

@ -0,0 +1,174 @@
/*
* Copyright (c) 2007, 2024, 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.
*
* 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.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Arrays;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
/*
* @test
* @bug 8048596
* @summary Check if wrong or empty AAD is rejected
*/
public class WrongAAD {
private static final String PROVIDER = System.getProperty("test.provider.name", "SunJCE");
private static final String TRANSFORMATION = "AES/GCM/NoPadding";
private static final int TEXT_SIZE = 800;
private static final int KEY_SIZE = 128;
private static final int AAD_SIZE = 128;
private final SecretKey key;
private final byte[] plainText;
private final Cipher encryptCipher;
public WrongAAD() throws Exception {
// init a secret key
KeyGenerator kg = KeyGenerator.getInstance("AES", PROVIDER);
kg.init(KEY_SIZE);
key = kg.generateKey();
// generate a plain text
plainText = Helper.generateBytes(TEXT_SIZE);
// init AADs
byte[] AAD = Helper.generateBytes(AAD_SIZE);
// init a cipher
encryptCipher = createCipher(Cipher.ENCRYPT_MODE, null);
encryptCipher.updateAAD(AAD);
}
public static void main(String[] args) throws Exception {
WrongAAD test = new WrongAAD();
test.decryptWithEmptyAAD();
test.decryptWithWrongAAD();
}
/*
* Attempt to decrypt a cipher text using Cipher object
* initialized without AAD used for encryption.
*/
private void decryptWithEmptyAAD() throws Exception {
System.out.println("decryptWithEmptyAAD() started");
// initialize it with empty AAD to get exception during decryption
Cipher decryptCipher = createCipher(Cipher.DECRYPT_MODE,
encryptCipher.getParameters());
try (ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
CipherOutputStream ciOutput = new CipherOutputStream(baOutput,
decryptCipher)) {
if (decrypt(ciOutput, baOutput)) {
throw new RuntimeException(
"Decryption has been perfomed successfully in"
+ " spite of the decrypt Cipher has NOT been"
+ " initialized with AAD");
}
}
System.out.println("decryptWithEmptyAAD() passed");
}
/*
* Attempt to decrypt the cipher text using Cipher object
* initialized with some fake AAD.
*/
private void decryptWithWrongAAD() throws Exception {
System.out.println("decrypt with wrong AAD");
// initialize it with wrong AAD to get an exception during decryption
Cipher decryptCipher = createCipher(Cipher.DECRYPT_MODE,
encryptCipher.getParameters());
byte[] someAAD = Helper.generateBytes(AAD_SIZE + 1);
decryptCipher.updateAAD(someAAD);
// init output stream
try (ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
CipherOutputStream ciOutput = new CipherOutputStream(baOutput,
decryptCipher);) {
if (decrypt(ciOutput, baOutput)) {
throw new RuntimeException(
"A decryption has been perfomed successfully in"
+ " spite of the decrypt Cipher has been"
+ " initialized with fake AAD");
}
}
System.out.println("Passed");
}
private boolean decrypt(CipherOutputStream ciOutput,
ByteArrayOutputStream baOutput) throws IOException {
try (ByteArrayInputStream baInput = new ByteArrayInputStream(plainText);
CipherInputStream ciInput = new CipherInputStream(baInput,
encryptCipher)) {
byte[] buffer = new byte[TEXT_SIZE];
int len = ciInput.read(buffer);
while (len != -1) {
ciOutput.write(buffer, 0, len);
len = ciInput.read(buffer);
}
ciOutput.flush();
byte[] recoveredText = baOutput.toByteArray();
System.out.println("recoveredText: " + new String(recoveredText));
/*
* See bug 8012900, AEADBadTagException is swalloed by CI/CO streams
* If recovered text is empty, than decryption failed
*/
if (recoveredText.length == 0) {
return false;
}
return Arrays.equals(plainText, recoveredText);
} catch (IllegalStateException e) {
System.out.println("Expected IllegalStateException: "
+ e.getMessage());
e.printStackTrace(System.out);
return false;
}
}
private Cipher createCipher(int mode, AlgorithmParameters params)
throws NoSuchAlgorithmException, NoSuchProviderException,
NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException {
Cipher cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
if (params != null) {
cipher.init(mode, key, params);
} else {
cipher.init(mode, key);
}
return cipher;
}
}

View file

@ -0,0 +1,187 @@
/*
* Copyright (c) 2014, 2024, 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.
*
* 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.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
/**
* @test
* @bug 8043836
* @summary Test AES ciphers with different modes and padding schemes (ECB mode
* doesn't use IV). The test tries 3 different read methods of
* CipherInputStream.
* @key randomness
*/
public class CICO {
private static final String ALGORITHM = "aEs";
private static final String[] MODES = { "PCBC", "ECb", "cbC", "cFB",
"cFB24", "cFB32", "Cfb40", "CFB72", "OfB", "OfB20", "OfB48",
"OfB56", "OFB64", "OFB112", "CFB112", "pCbC" };
private static final String[] PADDING = { "noPadding", "pkcs5padding" };
private static final String PROVIDER = System.getProperty("test.provider.name", "SunJCE");
private static final int NREADS = 3;
private static final int KEY_LENGTH = 128;
private final byte[] plainText = new byte[1600000];
public static void main(String argv[]) throws Exception {
CICO test = new CICO();
for (String mode : MODES) {
for (String pad : PADDING) {
for (int m = 0; m < NREADS; m++) {
test.runTest(ALGORITHM, mode, pad, m);
}
}
}
}
public void runTest(String algo, String mo, String pad, int whichRead) throws Exception {
Cipher ci1 = null;
Cipher ci2 = null;
byte[] iv = null;
AlgorithmParameterSpec aps = null;
SecretKey key = null;
try {
// Do initialization
Random rdm = new Random();
rdm.nextBytes(plainText);
KeyGenerator kg = KeyGenerator.getInstance(algo, PROVIDER);
if (!kg.getAlgorithm().equals(algo)) {
throw new RuntimeException("Unexpected algorithm <"
+ kg.getAlgorithm() + ">, expected value is <" + algo
+ ">");
}
kg.init(KEY_LENGTH);
key = kg.generateKey();
ci1 = Cipher.getInstance(algo + "/" + mo + "/" + pad, PROVIDER);
if (mo.equalsIgnoreCase("ECB")) {
ci1.init(Cipher.ENCRYPT_MODE, key);
} else {
ci1.init(Cipher.ENCRYPT_MODE, key, aps);
}
if (!mo.equalsIgnoreCase("ECB")) {
iv = ci1.getIV();
aps = new IvParameterSpec(iv);
} else {
aps = null;
}
ci2 = Cipher.getInstance(algo + "/" + mo + "/" + pad, PROVIDER);
if (mo.equalsIgnoreCase("ECB")) {
ci2.init(Cipher.DECRYPT_MODE, key);
} else {
ci2.init(Cipher.DECRYPT_MODE, key, aps);
}
ByteArrayInputStream baInput = new ByteArrayInputStream(plainText);
ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
try (CipherInputStream ciInput = new CipherInputStream(baInput, ci1);
CipherOutputStream ciOutput = new CipherOutputStream(
baOutput, ci2)) {
// According to specification, CipherInputStream does not support the
// mark and reset methods
if (ciInput.markSupported()) {
throw new RuntimeException(
"CipherInputStream unexpectedly supports the mark and reset methods");
}
// Read from the input and write to the output using 2 types
// of buffering : byte[] and int
switch (whichRead) {
case 0:
int buffer0 = ciInput.read();
while (buffer0 != -1) {
ciOutput.write(buffer0);
buffer0 = ciInput.read();
}
break;
case 1:
byte[] buffer1 = new byte[20];
int len1 = ciInput.read(buffer1);
while (len1 != -1) {
ciOutput.write(buffer1, 0, len1);
len1 = ciInput.read(buffer1);
}
break;
case NREADS - 1:
byte[] buffer2 = new byte[ci1
.getOutputSize(plainText.length)];
int offset2 = 0;
int len2 = 0;
while (len2 != -1) {
len2 = ciInput.read(buffer2, offset2, buffer2.length
- offset2);
offset2 += len2;
}
ciOutput.write(buffer2, 0, buffer2.length);
break;
}
}
// Get the output
byte[] recoveredText = new byte[baOutput.size()];
recoveredText = baOutput.toByteArray();
if (!java.util.Arrays.equals(plainText, recoveredText)) {
throw new RuntimeException(
"Original text is not equal with recovered text, with "
+ algo + "/" + mo + "/" + pad + "/" + whichRead);
}
// Compare input and output
} catch (NoSuchAlgorithmException e) {
//OFB20 is for negative testing
if (!mo.equalsIgnoreCase("OFB20")) {
System.out.println("Unexpected NoSuchAlgorithmException with "
+ algo + "/" + mo + "/" + pad + "/" + whichRead);
throw new RuntimeException("Test failed!");
}
} catch (IOException | NoSuchProviderException | NoSuchPaddingException
| InvalidKeyException | InvalidAlgorithmParameterException e) {
System.out.println("Unexpected Exception with "
+ algo + "/" + mo + "/" + pad + "/" + whichRead);
System.out.println("Test failed!");
throw e;
}
}
}

View file

@ -0,0 +1,147 @@
/*
* Copyright (c) 2014, 2024, 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.
*
* 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.
*/
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
/**
* @test
* @bug 8043836
* @summary Test AES ciphers with 4 different modes with NoPadding. Check if
* data before encryption and after decryption is the same.
* @key randomness
*/
public class CTR {
private static final String ALGORITHM = "AES";
private static final String PROVIDER =
System.getProperty("test.provider.name", "SunJCE");
private static final String[] MODES = {"CTR","CFB24","OFB32","GCM"};
private static final String PADDING = "NoPadding";
private static final int KEY_LENGTH = 128;
public static void main(String argv[]) throws Exception {
CTR test = new CTR();
for (String mode : MODES) {
test.runTest(ALGORITHM, mode, PADDING);
}
}
public void runTest(String algo, String mo, String pad) throws Exception {
Cipher ci = null;
byte[] iv = null;
AlgorithmParameterSpec aps = null;
SecretKey key = null;
try {
Random rdm = new Random();
byte[] plainText;
ci = Cipher.getInstance(algo + "/" + mo + "/" + pad, PROVIDER);
KeyGenerator kg = KeyGenerator.getInstance(algo, PROVIDER);
kg.init(KEY_LENGTH);
key = kg.generateKey();
for (int i = 0; i < 15; i++) {
plainText = new byte[1600 + i + 1];
rdm.nextBytes(plainText);
if (!mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.ENCRYPT_MODE, key, aps);
} else {
ci.init(Cipher.ENCRYPT_MODE, key);
}
byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
int offset = ci.update(plainText, 0, plainText.length,
cipherText, 0);
ci.doFinal(cipherText, offset);
if (!mo.equalsIgnoreCase("ECB")) {
iv = ci.getIV();
aps = new IvParameterSpec(iv);
} else {
aps = null;
}
if (!mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.DECRYPT_MODE, key, aps);
} else {
ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
}
byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
int len = ci.doFinal(cipherText, 0, cipherText.length,
recoveredText);
byte[] tmp = new byte[len];
for (int j = 0; j < len; j++) {
tmp[j] = recoveredText[j];
}
Arrays.toString(plainText);
if (!java.util.Arrays.equals(plainText, tmp)) {
System.out.println("Original: ");
dumpBytes(plainText);
System.out.println("Recovered: ");
dumpBytes(tmp);
throw new RuntimeException("Original text is not equal with recovered text, with mode:" + mo);
}
}
} catch (NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException
| InvalidKeyException | InvalidAlgorithmParameterException
| ShortBufferException | IllegalBlockSizeException
| BadPaddingException e) {
System.out.println("Test failed!");
throw e;
}
}
private void dumpBytes(byte[] bytes){
for (byte b : bytes){
System.out.print(Integer.toHexString(b));
}
System.out.println();
}
}

View file

@ -0,0 +1,157 @@
/*
* Copyright (c) 2014, 2024, 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.
*
* 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.
*/
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
/**
* @test
* @bug 8043836
* @summary Test AES ciphers with different modes and padding schemes (ECB mode
* doesn't use IV). The test tries 3 different read methods of
* CipherInputStream.
* @key randomness
*/
public class Padding {
private static final String ALGORITHM = "AES";
private static final String PROVIDER =
System.getProperty("test.provider.name", "SunJCE");
private static final String[] MODES_PKCS5PAD = {
"ECb", "CbC", "PCBC", "OFB",
"OFB150", "cFB", "CFB7", "cFB8", "cFB16", "cFB24", "cFB32",
"Cfb40", "cfB48", "cfB56", "cfB64", "cfB72", "cfB80", "cfB88",
"cfB96", "cfb104", "cfB112", "cfB120", "OFB8", "OFB16", "OFB24",
"OFB32", "OFB40", "OFB48", "OFB56", "OFB64", "OFB72", "OFB80",
"OFB88", "OFB96", "OFB104", "OFB112", "OFB120" };
private static final String[] MODES_NOPAD = { "CTR", "CTS", "GCM" };
private static final int KEY_LENGTH = 128;
public static void main(String argv[]) throws Exception {
Padding test = new Padding();
for (String mode : MODES_PKCS5PAD) {
test.runTest(ALGORITHM, mode, "PKCS5Padding");
}
for (String mode : MODES_NOPAD) {
test.runTest(ALGORITHM, mode, "NoPadding");
}
}
public void runTest(String algo, String mo, String pad) throws Exception {
Cipher ci = null;
byte[] iv = null;
AlgorithmParameterSpec aps = null;
SecretKey key = null;
try {
Random rdm = new Random();
byte[] plainText;
ci = Cipher.getInstance(algo + "/" + mo + "/" + pad, PROVIDER);
KeyGenerator kg = KeyGenerator.getInstance(algo, PROVIDER);
kg.init(KEY_LENGTH);
key = kg.generateKey();
for (int i = 0; i < 15; i++) {
plainText = new byte[1600 + i + 1];
rdm.nextBytes(plainText);
if (!mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.ENCRYPT_MODE, key, aps);
} else {
ci.init(Cipher.ENCRYPT_MODE, key);
}
byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
int offset = ci.update(plainText, 0, plainText.length,
cipherText, 0);
ci.doFinal(cipherText, offset);
if (!mo.equalsIgnoreCase("ECB")) {
iv = ci.getIV();
aps = new IvParameterSpec(iv);
} else {
aps = null;
}
if (!mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.DECRYPT_MODE, key, aps);
} else {
ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
}
byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
int len = ci.doFinal(cipherText, 0, cipherText.length,
recoveredText);
byte[] tmp = new byte[len];
for (int j = 0; j < len; j++) {
tmp[j] = recoveredText[j];
}
if (!java.util.Arrays.equals(plainText, tmp)) {
System.out.println("Original: ");
dumpBytes(plainText);
System.out.println("Recovered: ");
dumpBytes(tmp);
throw new RuntimeException(
"Original text is not equal with recovered text, with mode:"
+ mo);
}
}
} catch (NoSuchAlgorithmException e) {
//CFB7 and OFB150 are for negative testing
if (!mo.equalsIgnoreCase("CFB7") && !mo.equalsIgnoreCase("OFB150")) {
System.out
.println("Unexpected NoSuchAlgorithmException with mode: "
+ mo);
throw new RuntimeException("Test failed!");
}
} catch ( NoSuchProviderException | NoSuchPaddingException
| InvalidKeyException | InvalidAlgorithmParameterException
| ShortBufferException | IllegalBlockSizeException
| BadPaddingException e) {
System.out.println("Test failed!");
throw e;
}
}
private void dumpBytes(byte[] bytes) {
for (byte b : bytes) {
System.out.print(Integer.toHexString(b));
}
System.out.println();
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4511676
* @summary Verify that AES cipher.init method check key size correctly
* @author Valerie Peng
*/
import java.io.PrintStream;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.Provider;
public class Test4511676 {
private static final String ALGO = "AES";
private static final int KEYSIZE = 16; // in bytes
public boolean execute() throws Exception {
Cipher ci = Cipher.getInstance(ALGO,
System.getProperty("test.provider.name", "SunJCE"));
// TEST FIX 4511676
KeyGenerator kg = KeyGenerator.getInstance(ALGO,
System.getProperty("test.provider.name", "SunJCE"));
kg.init(KEYSIZE*8);
SecretKey key = kg.generateKey();
try {
ci.init(Cipher.ENCRYPT_MODE, key);
} catch (InvalidKeyException ex) {
throw new Exception("key length is mis-intepreted!");
}
// passed all tests...hooray!
return true;
}
public static void main (String[] args) throws Exception {
Test4511676 test = new Test4511676();
String testName = test.getClass().getName() + "[" + ALGO +
"]";
if (test.execute()) {
System.out.println(testName + ": Passed!");
}
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4512524
* @summary Verify that AES cipher can work with mode "CBC", "OFB", "CFB"
* @author Valerie Peng
*/
import java.io.PrintStream;
import java.security.*;
import java.security.spec.*;
import java.util.Random;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.Provider;
public class Test4512524 {
private static final String ALGO = "AES";
private static final String PADDING = "NoPadding";
private static final int KEYSIZE = 16; // in bytes
public void execute(String mode) throws Exception {
String transformation = ALGO+"/"+mode+"/"+PADDING;
Cipher ci = Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
// TEST FIX 4512524
KeyGenerator kg = KeyGenerator.getInstance(ALGO,
System.getProperty("test.provider.name", "SunJCE"));
kg.init(KEYSIZE*8);
SecretKey key = kg.generateKey();
try{
AlgorithmParameterSpec aps = null;
ci.init(Cipher.ENCRYPT_MODE, key, aps);
} catch (NullPointerException ex) {
throw new Exception("null parameter is not handled correctly!");
}
// passed all tests...hooray!
System.out.println(transformation + ": Passed");
}
public static void main (String[] args) throws Exception {
Test4512524 test = new Test4512524();
test.execute("CBC");
test.execute("GCM");
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4512704
* @summary Verify that AES cipher can generate default IV in encrypt mode
* @author Valerie Peng
*/
import java.io.PrintStream;
import java.security.*;
import java.security.spec.*;
import java.util.Random;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.Provider;
public class Test4512704 {
private static final String ALGO = "AES";
private static final String PADDING = "NoPadding";
private static final int KEYSIZE = 16; // in bytes
public void execute(String mode) throws Exception {
AlgorithmParameterSpec aps = null;
String transformation = ALGO + "/" + mode + "/"+PADDING;
Cipher ci = Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
KeyGenerator kg = KeyGenerator.getInstance(ALGO,
System.getProperty("test.provider.name", "SunJCE"));
kg.init(KEYSIZE*8);
SecretKey key = kg.generateKey();
// TEST FIX 4512704
try {
ci.init(Cipher.ENCRYPT_MODE, key, aps);
} catch(InvalidAlgorithmParameterException ex) {
throw new Exception("parameter should be generated when null is specified!");
}
System.out.println(transformation + ": Passed");
}
public static void main (String[] args) throws Exception {
Test4512704 test = new Test4512704();
test.execute("CBC");
test.execute("GCM");
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4513830
* @summary Verify the output size returned by AES cipher.getOutputSize
* method in DECRYPT mode does not add extra bytes for padding
* @author Valerie Peng
* @key randomness
*/
import java.io.PrintStream;
import java.security.*;
import java.security.spec.*;
import java.util.Random;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.Provider;
public class Test4513830 {
private static final String ALGO = "AES";
private static final String MODE = "ECB";
private static final String PADDING = "PKCS5Padding";
private static final int KEYSIZE = 16; // in bytes
private static final int TEXTLENGTHS[] = {
16, 17, 18, 19, 20, 21, 22, 23 };
public boolean execute() throws Exception {
Random rdm = new Random();
byte[] plainText=new byte[125];
rdm.nextBytes(plainText);
Cipher ci = Cipher.getInstance(ALGO+"/"+MODE+"/"+PADDING,
System.getProperty("test.provider.name", "SunJCE"));
// TEST FIX 4513830
KeyGenerator kg = KeyGenerator.getInstance(ALGO,
System.getProperty("test.provider.name", "SunJCE"));
kg.init(KEYSIZE*8);
SecretKey key = kg.generateKey();
ci.init(Cipher.DECRYPT_MODE, key);
int recoveredTextLength = ci.getOutputSize(16);
if (recoveredTextLength != 16) {
throw new Exception("output size should not increase when decrypting!");
}
// BONUS TESTS
// 1. call getOutputSize with various lengths and see if
// the returned size is correct.
for (int i=0; i<TEXTLENGTHS.length; i++) {
ci.init(Cipher.ENCRYPT_MODE, key);
int cipherTextLength = ci.getOutputSize(TEXTLENGTHS[i]);
if (cipherTextLength != 32) {
throw new Exception("output size " + cipherTextLength
+ " for input size " + TEXTLENGTHS[i]
+ " when encrypting is wrong!");
}
}
// passed all tests...hooray!
return true;
}
public static void main (String[] args) throws Exception {
Test4513830 test = new Test4513830();
String testName = test.getClass().getName() + "[" + ALGO +
"/" + MODE + "/" + PADDING + "]";
if (test.execute()) {
System.out.println(testName + ": Passed!");
}
}
}

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4517355
* @summary Verify that AES cipher.doFinal method does NOT need more
* than necessary bytes in decrypt mode
* @author Valerie Peng
* @key randomness
*/
import java.io.PrintStream;
import java.security.*;
import java.security.spec.*;
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.Provider;
public class Test4517355 {
private static final String ALGO = "AES";
private static final int KEYSIZE = 16; // in bytes
private static byte[] plainText = new byte[125];
public void execute(String mode, String padding) throws Exception {
String transformation = ALGO + "/" + mode + "/" + padding;
Cipher ci = Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
KeyGenerator kg = KeyGenerator.getInstance(ALGO,
System.getProperty("test.provider.name", "SunJCE"));
kg.init(KEYSIZE*8);
SecretKey key = kg.generateKey();
// TEST FIX 4517355
ci.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = ci.doFinal(plainText);
if (mode.equalsIgnoreCase("GCM")) {
AlgorithmParameters params = ci.getParameters();
ci.init(Cipher.DECRYPT_MODE, key, params);
} else {
byte[] iv = ci.getIV();
AlgorithmParameterSpec aps = new IvParameterSpec(iv);
ci.init(Cipher.DECRYPT_MODE, key, aps);
}
byte[] recoveredText = new byte[plainText.length];
try {
int len = ci.doFinal(cipherText, 0, cipherText.length,
recoveredText);
} catch (ShortBufferException ex) {
throw new Exception("output buffer is the right size!");
}
// BONUS TESTS
// 1. make sure the recoveredText is the same as the plainText
if (!Arrays.equals(plainText, recoveredText)) {
throw new Exception("encryption/decryption does not work!");
}
// 2. make sure encryption does happen
if (Arrays.equals(plainText, cipherText)) {
throw new Exception("encryption does not work!");
}
// 3. make sure padding is working
if (padding.equalsIgnoreCase("PKCS5Padding")) {
if ((cipherText.length/16)*16 != cipherText.length) {
throw new Exception("padding does not work!");
}
}
System.out.println(transformation + ": Passed");
}
public static void main (String[] args) throws Exception {
Test4517355 test = new Test4517355();
Random rdm = new Random();
rdm.nextBytes(test.plainText);
test.execute("CBC", "PKCS5Padding");
test.execute("GCM", "NoPadding");
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4626070
* @summary Verify that AES cipher can wrap and unwrap keys
* @author Valerie Peng
*/
import java.security.*;
import javax.crypto.*;
import java.util.*;
public class Test4626070 {
private static final String ALGO = "AES";
private static final int KEYSIZE = 16; // in bytes
public void execute(String mode, String padding) throws Exception {
String transformation = ALGO + "/" + mode + "/" + padding;
Cipher ci = Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
KeyGenerator kg = KeyGenerator.getInstance(ALGO,
System.getProperty("test.provider.name", "SunJCE"));
kg.init(KEYSIZE*8);
SecretKey key = kg.generateKey();
AlgorithmParameters params = ci.getParameters();
// TEST FIX 4626070
ci.init(Cipher.WRAP_MODE, key, params);
byte[] wrappedKeyEncoding = ci.wrap(key);
params = ci.getParameters();
ci.init(Cipher.UNWRAP_MODE, key, params);
Key recoveredKey = ci.unwrap(wrappedKeyEncoding, "AES",
Cipher.SECRET_KEY);
if (!key.equals(recoveredKey)) {
throw new Exception(
"key after wrap/unwrap is different from the original!");
}
System.out.println(transformation + ": Passed");
}
public static void main (String[] args) throws Exception {
Test4626070 test = new Test4626070();
test.execute("CBC", "PKCS5Padding");
test.execute("GCM", "NoPadding");
}
}

View file

@ -0,0 +1,149 @@
/*
* Copyright (c) 2014, 2024, 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.
*
* 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.
*/
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.HexFormat;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* @test
* @bug 8043836
* @summary Test AES ciphers with different modes and padding schemes (ECB mode
* doesn't use IV).
* @author Liwen Wang
* @author Parag Salvi
*/
public class TestAESCipher {
private static final String ALGORITHM = "AES";
private static final String PROVIDER = System.getProperty("test.provider.name", "SunJCE");
private static final String[] MODES = { "ECb", "CbC", "CTR", "PCBC", "OFB",
"OFB150", "cFB", "CFB7", "cFB8", "cFB16", "cFB24", "cFB32",
"Cfb40", "cfB48", "cfB56", "cfB64", "cfB72", "cfB80", "cfB88",
"cfB96", "cfb104", "cfB112", "cfB120", "OFB8", "OFB16", "OFB24",
"OFB32", "OFB40", "OFB48", "OFB56", "OFB64", "OFB72", "OFB80",
"OFB88", "OFB96", "OFB104", "OFB112", "OFB120", "GCM" };
private static final String[] PADDING = { "NoPadding", "PKCS5Padding" };
private static final int KEY_LENGTH = 16;
static byte[] plainText = new byte[128];
static byte[] key = new byte[KEY_LENGTH];
public static void main(String argv[]) throws Exception {
TestAESCipher test = new TestAESCipher();
for (String mode : MODES) {
int padKinds = 1;
if (mode.equalsIgnoreCase("ECB") || mode.equalsIgnoreCase("PCBC")
|| mode.equalsIgnoreCase("CBC")) {
padKinds = PADDING.length;
}
for (int k = 0; k < padKinds; k++) {
test.runTest(ALGORITHM, mode, PADDING[k]);
}
}
}
public void runTest(String algo, String mo, String pad) throws Exception {
Cipher ci;
System.out.println("Testing " + algo + "/" + mo + "/" + pad);
byte[] iv = new byte[16];
AlgorithmParameterSpec aps = new GCMParameterSpec(128, iv);
SecretKey key = new SecretKeySpec(this.key, 0, KEY_LENGTH,"AES");
try {
// Initialization
ci = Cipher.getInstance(algo + "/" + mo + "/" + pad, PROVIDER);
// encrypt
if (mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.ENCRYPT_MODE, key, aps);
} else if (mo.equalsIgnoreCase("ECB")) {
ci.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameterSpec)null);
} else {
ci.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
}
byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
int offset = ci.update(plainText, 0, plainText.length, cipherText,
0);
ci.doFinal(cipherText, offset);
if (!mo.equalsIgnoreCase("ECB")) {
iv = ci.getIV();
aps = new IvParameterSpec(iv);
} else {
aps = null;
}
if (!mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.DECRYPT_MODE, key, aps);
} else {
ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
}
byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
int len = ci.doFinal(cipherText, 0, cipherText.length,
recoveredText);
// Comparison
if (!java.util.Arrays.equals(plainText, 0 , plainText.length,
recoveredText, 0, len)) {
System.out.println("Original: ");
System.out.println(HexFormat.of().formatHex(plainText));
System.out.println("Recovered: ");
System.out.println(HexFormat.of().
formatHex(recoveredText, 0, len));
throw new RuntimeException("Original text is not equal with " +
"recovered text, with mode:" + mo);
}
} catch (NoSuchAlgorithmException e) {
//CFB7 and OFB150 are for negative testing
if (!mo.equalsIgnoreCase("CFB7") && !mo.equalsIgnoreCase("OFB150")) {
System.out.println("Unexpected NoSuchAlgorithmException with" +
" mode: " + mo);
throw new RuntimeException("Test failed!");
}
} catch ( NoSuchProviderException | NoSuchPaddingException
| InvalidKeyException | InvalidAlgorithmParameterException
| ShortBufferException | IllegalBlockSizeException
| BadPaddingException e) {
System.out.println("Test failed!");
throw e;
}
}
}

View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2012, 2024, 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.
*
* 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.
*/
import java.io.PrintStream;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class Dynamic {
static final String ALGORITHM = "AES";
static final String[] MODE = {
"ECb", "CbC", "CTR", "PCBC", "OFB", "OFB150", "cFB", "CFB7",
"cFB8", "cFB16", "cFB24", "cFB32", "Cfb40", "cfB48", "cfB56",
"cfB64", "cfB72", "cfB80", "cfB88", "cfB96", "cfb104", "cfB112",
"cfB120", "cfB128", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
"OFB48", "OFB56", "OFB64", "OFB72", "OFB80", "OFB88", "OFB96",
"OFB104", "OFB112", "OFB120", "OFB128", "GCM"
};
static final String[] PADDING = {
"NoPadding", "PKCS5Padding", "ISO10126Padding"
};
static final String PROVIDER = System.getProperty("test.provider.name", "SunJCE");
Cipher ci = null;
byte[] iv = null;
AlgorithmParameterSpec aps = null;
SecretKey key = null;
int keyStrength;
static int DefaultSize = 128;
public void run(String[] argv) throws Exception {
if (!runAllTest(argv, System.out)) {
throw new Exception("Test Failed");
}
}
protected boolean runAllTest(String argv[], PrintStream out) {
boolean result = true;
StringBuilder failedList = new StringBuilder();
int failedCnt = 0;
int testCount = 0;
int padKinds; // how many kinds of padding mode such as PKCS5padding and
// NoPadding.
try {
for (int i = 0; i < 3; i++) {
keyStrength = DefaultSize + i * 64; // obtain the key size 128,
// 192, 256
for (int j = 0; j < MODE.length; j++) {
if (MODE[j].equalsIgnoreCase("ECB")
|| MODE[j].equalsIgnoreCase("PCBC")
|| MODE[j].equalsIgnoreCase("CBC")) {
padKinds = PADDING.length;
} else {
padKinds = 1;
}
for (int k = 0; k < padKinds; k++) {
testCount++;
try {
if (!runTest(ALGORITHM, MODE[j], PADDING[k])) {
result = false;
failedCnt++;
failedList.append(ALGORITHM + "/" + MODE[j]
+ "/" + PADDING[k] + " ");
}
} catch (Exception e) {
e.printStackTrace();
result = false;
failedCnt++;
failedList.append(ALGORITHM + "/" + MODE[j] + "/"
+ PADDING[k] + " ");
}
}
}
}
if (result) {
out.println("STATUS:Passed. Test " + testCount
+ " cases, All Passed");
return true;
}
out.println("STATUS:Failed. " + failedCnt + " Failed: "
+ failedList);
return false;
} catch (Exception ex) {
ex.printStackTrace();
out.println("STATUS:Failed. Unexpected Exception: " + ex);
return false;
}
}
protected boolean runTest(String algo, String mo, String pad)
throws Exception {
boolean result = true;
try {
byte[] plainText = new byte[160000];
new Random().nextBytes(plainText);
String transformation = algo + "/" + mo + "/" + pad;
ci = Cipher.getInstance(transformation, PROVIDER);
KeyGenerator kg = KeyGenerator.getInstance(algo, PROVIDER);
if (keyStrength > Cipher.getMaxAllowedKeyLength(transformation)) {
// skip if this key length is larger than what's
// configured in the jce jurisdiction policy files
System.out.println(keyStrength
+ " is larger than what's configured "
+ "in the jce jurisdiction policy files");
return result;
}
kg.init(keyStrength);
key = kg.generateKey();
if (!mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.ENCRYPT_MODE, key, aps);
} else {
ci.init(Cipher.ENCRYPT_MODE, key);
}
byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
int offset = ci.update(plainText, 0, plainText.length, cipherText,
0);
ci.doFinal(cipherText, offset);
ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
int len = ci.doFinal(cipherText, 0, cipherText.length,
recoveredText);
byte[] tmp = new byte[len];
for (int i = 0; i < len; i++) {
tmp[i] = recoveredText[i];
}
result = Arrays.equals(plainText, tmp);
} catch (NoSuchAlgorithmException nsaEx) {
// CFB7 and OFB150 are negative test,SunJCE not support this
// algorithm
result = mo.equalsIgnoreCase("CFB7")
|| mo.equalsIgnoreCase("OFB150");
if (!result) {
// only report unexpected exception
nsaEx.printStackTrace();
}
}
return result;
}
}

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 2015, 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.
*
* 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.
*/
/*
* @test
* @bug 8044193
* @summary Test AES ciphers with different modes and padding schemes with
* default provider
*/
public class TestAESWithDefaultProvider extends Dynamic {
public static void main(String argv[]) throws Exception {
new TestAESWithDefaultProvider().run(argv);
}
}

View file

@ -0,0 +1,39 @@
/* Copyright (c) 2012, 2024, 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.
*
* 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.
*/
import java.security.Security;
/*
* @test
* @bug 8044193
* @summary Test AES ciphers with different modes and padding schemes after
* remove then add provider.
* @modules java.base/com.sun.crypto.provider
*/
public class TestAESWithProviderChange extends Dynamic {
public static void main(String argv[]) throws Exception {
Security.removeProvider(PROVIDER);
Security.addProvider(new com.sun.crypto.provider.SunJCE());
new TestAESWithProviderChange().run(argv);
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2012, 2024, 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.
*
* 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.
*/
import java.security.*;
import java.security.Provider;
/*
* @test
* @bug 8044193
* @summary Test AES ciphers with different modes and padding schemes after
* remove default provider then add it back.
*/
public class TestAESWithRemoveAddProvider extends Dynamic {
public static void main(String argv[]) throws Exception {
Provider pJCE = Security.getProvider(PROVIDER);
Security.removeProvider(PROVIDER);
Security.addProvider(pJCE);
new TestAESWithRemoveAddProvider().run(argv);
}
}

View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 2013, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 8012637
* @library ../UTIL
* @build TestUtil
* @run main TestCICOWithGCM
* @summary Test CipherInputStream/OutputStream with AES GCM mode.
* @author Valerie Peng
* @key randomness
*/
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.math.*;
import java.io.*;
import java.util.*;
public class TestCICOWithGCM {
public static void main(String[] args) throws Exception {
//init Secret Key
KeyGenerator kg = KeyGenerator.getInstance("AES",
System.getProperty("test.provider.name", "SunJCE"));
kg.init(128);
SecretKey key = kg.generateKey();
//do initialization of the plainText
byte[] plainText = new byte[800];
Random rdm = new Random();
rdm.nextBytes(plainText);
//init ciphers
Cipher encCipher = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
encCipher.init(Cipher.ENCRYPT_MODE, key);
Cipher decCipher = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
decCipher.init(Cipher.DECRYPT_MODE, key, encCipher.getParameters());
//init cipher streams
ByteArrayInputStream baInput = new ByteArrayInputStream(plainText);
CipherInputStream ciInput = new CipherInputStream(baInput, encCipher);
ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
CipherOutputStream ciOutput = new CipherOutputStream(baOutput, decCipher);
//do test
byte[] buffer = new byte[800];
int len = ciInput.read(buffer);
System.out.println("read " + len + " bytes from input buffer");
while (len != -1) {
ciOutput.write(buffer, 0, len);
System.out.println("wite " + len + " bytes to output buffer");
len = ciInput.read(buffer);
if (len != -1) {
System.out.println("read " + len + " bytes from input buffer");
} else {
System.out.println("finished reading");
}
}
ciOutput.flush();
ciInput.close();
ciOutput.close();
byte[] recovered = baOutput.toByteArray();
System.out.println("recovered " + recovered.length + " bytes");
if (!Arrays.equals(plainText, recovered)) {
throw new RuntimeException("diff check failed!");
} else {
System.out.println("diff check passed");
}
}
}

View file

@ -0,0 +1,109 @@
/*
* Copyright (c) 2013, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 8012900
* @library ../UTIL
* @build TestUtil
* @run main TestCICOWithGCMAndAAD
* @summary Test CipherInputStream/OutputStream with AES GCM mode with AAD.
* @author Valerie Peng
* @key randomness
*/
import java.io.*;
import java.security.*;
import java.util.*;
import javax.crypto.*;
public class TestCICOWithGCMAndAAD {
public static void main(String[] args) throws Exception {
//init Secret Key
KeyGenerator kg = KeyGenerator.getInstance("AES",
System.getProperty("test.provider.name", "SunJCE"));
kg.init(128);
SecretKey key = kg.generateKey();
//Do initialization of the plainText
byte[] plainText = new byte[700];
Random rdm = new Random();
rdm.nextBytes(plainText);
byte[] aad = new byte[128];
rdm.nextBytes(aad);
byte[] aad2 = aad.clone();
aad2[50]++;
Cipher encCipher = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
encCipher.init(Cipher.ENCRYPT_MODE, key);
encCipher.updateAAD(aad);
Cipher decCipher = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
decCipher.init(Cipher.DECRYPT_MODE, key, encCipher.getParameters());
decCipher.updateAAD(aad);
byte[] recovered = test(encCipher, decCipher, plainText);
if (!Arrays.equals(plainText, recovered)) {
throw new Exception("sameAAD: diff check failed!");
} else System.out.println("sameAAD: passed");
encCipher.init(Cipher.ENCRYPT_MODE, key);
encCipher.updateAAD(aad2);
recovered = test(encCipher, decCipher, plainText);
if (recovered != null && recovered.length != 0) {
throw new Exception("diffAAD: no data should be returned!");
} else System.out.println("diffAAD: passed");
}
private static byte[] test(Cipher encCipher, Cipher decCipher, byte[] plainText)
throws Exception {
//init cipher streams
ByteArrayInputStream baInput = new ByteArrayInputStream(plainText);
CipherInputStream ciInput = new CipherInputStream(baInput, encCipher);
ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
CipherOutputStream ciOutput = new CipherOutputStream(baOutput, decCipher);
//do test
byte[] buffer = new byte[200];
int len = ciInput.read(buffer);
System.out.println("read " + len + " bytes from input buffer");
while (len != -1) {
ciOutput.write(buffer, 0, len);
System.out.println("wite " + len + " bytes to output buffer");
len = ciInput.read(buffer);
if (len != -1) {
System.out.println("read " + len + " bytes from input buffer");
} else {
System.out.println("finished reading");
}
}
ciOutput.flush();
ciInput.close();
ciOutput.close();
return baOutput.toByteArray();
}
}

View file

@ -0,0 +1,184 @@
/*
* Copyright (c) 2013, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 8026943 8027575
* @summary Verify that same buffer can be used as input and output when
* using Cipher objects.
* @author Valerie Peng
*/
import java.security.*;
import java.security.spec.*;
import java.util.Arrays;
import javax.crypto.*;
import javax.crypto.spec.*;
public class TestCopySafe {
private static boolean DEBUG = false;
private static int INPUT_LENGTH = 160; // must be multiple of block size
private static byte[] PT = new byte[INPUT_LENGTH];
private static SecretKey KEY = new SecretKeySpec(new byte[16], "AES");
private static byte[] IV = new byte[16];
private static int[] OFFSETS = { 1, 8, 9, 16, 17, 32, 33 };
private static final String[] MODES = {
"ECB", "CBC", "PCBC", "CTR", "CTS",
"CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40",
"CFB48", "CFB56", "CFB64",
"OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
"OFB48", "OFB56", "OFB64",
"GCM"
};
public static void main(String[] argv) throws Exception {
Provider p = Security.getProvider(
System.getProperty("test.provider.name", "SunJCE"));
AlgorithmParameterSpec params = null;
boolean result = true;
for (String mode : MODES) {
String transformation = "AES/" + mode + "/NoPadding";
boolean isGCM = (mode == "GCM");
if (isGCM) {
params = new GCMParameterSpec(128, IV);
} else if (mode != "ECB") {
params = new IvParameterSpec(IV);
}
Cipher c = Cipher.getInstance(transformation, p);
System.out.println("Testing " + transformation + ":");
for (int offset : OFFSETS) {
System.out.print("=> offset " + offset + ": ");
try {
test(c, params, offset, isGCM);
System.out.println("Passed");
} catch(Exception ex) {
ex.printStackTrace();
result = false;
continue;
}
}
}
if (!result) {
throw new Exception("One or more test failed");
}
}
private static void test(Cipher c, AlgorithmParameterSpec params,
int offset, boolean isGCM) throws Exception {
// Test encryption first
if (isGCM) {
// re-init with only key value first to bypass the
// Key+IV-uniqueness check for GCM encryption
c.init(Cipher.ENCRYPT_MODE, KEY);
}
c.init(Cipher.ENCRYPT_MODE, KEY, params);
byte[] answer = c.doFinal(PT);
byte[] pt2 = Arrays.copyOf(PT, answer.length + offset);
// #1: outOfs = inOfs = 0
if (isGCM) {
c.init(Cipher.ENCRYPT_MODE, KEY);
c.init(Cipher.ENCRYPT_MODE, KEY, params);
}
c.doFinal(pt2, 0, PT.length, pt2, 0);
if (!isTwoArraysEqual(pt2, 0, answer, 0, answer.length)) {
throw new Exception("Enc#1 diff check failed!");
} else if (DEBUG) {
System.out.println("Enc#1 diff check passed");
}
// #2: inOfs = 0, outOfs = offset
System.arraycopy(PT, 0, pt2, 0, PT.length);
if (isGCM) {
c.init(Cipher.ENCRYPT_MODE, KEY);
c.init(Cipher.ENCRYPT_MODE, KEY, params);
}
c.doFinal(pt2, 0, PT.length, pt2, offset);
if (!isTwoArraysEqual(pt2, offset, answer, 0, answer.length)) {
throw new Exception("Enc#2 diff check failed");
} else if (DEBUG) {
System.out.println("Enc#2 diff check passed");
}
// #3: inOfs = offset, outOfs = 0
System.arraycopy(PT, 0, pt2, offset, PT.length);
if (isGCM) {
c.init(Cipher.ENCRYPT_MODE, KEY);
c.init(Cipher.ENCRYPT_MODE, KEY, params);
}
c.doFinal(pt2, offset, PT.length, pt2, 0);
if (!isTwoArraysEqual(pt2, 0, answer, 0, answer.length)) {
throw new Exception("Enc#3 diff check failed");
} else if (DEBUG) {
System.out.println("Enc#3 diff check passed");
}
// Test decryption now, we should get back PT as a result
c.init(Cipher.DECRYPT_MODE, KEY, params);
pt2 = Arrays.copyOf(answer, answer.length + offset);
// #1: outOfs = inOfs = 0
c.doFinal(pt2, 0, answer.length, pt2, 0);
if (!isTwoArraysEqual(pt2, 0, PT, 0, PT.length)) {
throw new Exception("Dec#1 diff check failed!");
} else if (DEBUG) {
System.out.println("Dec#1 diff check passed");
}
// #2: inOfs = 0, outOfs = offset
System.arraycopy(answer, 0, pt2, 0, answer.length);
c.doFinal(pt2, 0, answer.length, pt2, offset);
if (!isTwoArraysEqual(pt2, offset, PT, 0, PT.length)) {
throw new Exception("Dec#2 diff check failed");
} else if (DEBUG) {
System.out.println("Dec#2 diff check passed");
}
// #3: inOfs = offset, outOfs = 0
System.arraycopy(answer, 0, pt2, offset, answer.length);
c.doFinal(pt2, offset, answer.length, pt2, 0);
if (!isTwoArraysEqual(pt2, 0, PT, 0, PT.length)) {
throw new Exception("Dec#3 diff check failed");
} else if (DEBUG) {
System.out.println("Dec#3 diff check passed");
}
}
private static boolean isTwoArraysEqual(byte[] a, int aOff, byte[] b, int bOff,
int len) {
for (int i = 0; i < len; i++) {
if (a[aOff + i] != b[bOff + i]) {
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,178 @@
/*
* Copyright (c) 2013, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 6996769
* @library ../UTIL
* @build TestUtil
* @run main TestGCMKeyAndIvCheck
* @summary Ensure that same key+iv can't be repeated used for encryption.
* @author Valerie Peng
*/
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.math.*;
import java.util.*;
public class TestGCMKeyAndIvCheck {
private static final byte[] AAD = new byte[5];
private static final byte[] PT = new byte[18];
private static void checkISE(Cipher c) throws Exception {
// Subsequent encryptions should fail
try {
c.updateAAD(AAD);
throw new Exception("Should throw ISE for updateAAD()");
} catch (IllegalStateException ise) {
// expected
}
try {
c.update(PT);
throw new Exception("Should throw ISE for update()");
} catch (IllegalStateException ise) {
// expected
}
try {
c.doFinal(PT);
throw new Exception("Should throw ISE for doFinal()");
} catch (IllegalStateException ise) {
// expected
}
}
public void test() throws Exception {
Cipher c = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
SecretKey key = new SecretKeySpec(new byte[16], "AES");
// First try parameter-less init.
c.init(Cipher.ENCRYPT_MODE, key);
c.updateAAD(AAD);
byte[] ctPlusTag = c.doFinal(PT);
// subsequent encryption should fail unless re-init w/ different key+iv
checkISE(c);
// Validate the retrieved parameters against the IV and tag length.
AlgorithmParameters params = c.getParameters();
if (params == null) {
throw new Exception("getParameters() should not return null");
}
GCMParameterSpec spec = params.getParameterSpec(GCMParameterSpec.class);
if (spec.getTLen() != (ctPlusTag.length - PT.length)*8) {
throw new Exception("Parameters contains incorrect TLen value");
}
if (!Arrays.equals(spec.getIV(), c.getIV())) {
throw new Exception("Parameters contains incorrect IV value");
}
// Should be ok to use the same key+iv for decryption
c.init(Cipher.DECRYPT_MODE, key, params);
c.updateAAD(AAD);
byte[] recovered = c.doFinal(ctPlusTag);
if (!Arrays.equals(recovered, PT)) {
throw new Exception("decryption result mismatch");
}
// Now try to encrypt again using the same key+iv; should fail also
try {
c.init(Cipher.ENCRYPT_MODE, key, params);
throw new Exception("Should throw exception when same key+iv is used");
} catch (InvalidAlgorithmParameterException iape) {
// expected
}
// Now try to encrypt again using parameter-less init; should work
c.init(Cipher.ENCRYPT_MODE, key);
c.doFinal(PT);
// make sure a different iv is used
byte[] iv = c.getIV();
if (Arrays.equals(spec.getIV(), iv)) {
throw new Exception("IV should be different now");
}
// Now try to encrypt again using a different parameter; should work
c.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, new byte[30]));
c.updateAAD(AAD);
c.doFinal(PT);
// subsequent encryption should fail unless re-init w/ different key+iv
checkISE(c);
// Now try decryption twice in a row; no re-init required and
// same parameters is used.
c.init(Cipher.DECRYPT_MODE, key, params);
c.updateAAD(AAD);
recovered = c.doFinal(ctPlusTag);
c.updateAAD(AAD);
recovered = c.doFinal(ctPlusTag);
if (!Arrays.equals(recovered, PT)) {
throw new Exception("decryption result mismatch");
}
// Now try decryption again and re-init using the same parameters
c.init(Cipher.DECRYPT_MODE, key, params);
c.updateAAD(AAD);
recovered = c.doFinal(ctPlusTag);
// init to decrypt w/o parameters; should fail with IKE as
// javadoc specified
try {
c.init(Cipher.DECRYPT_MODE, key);
throw new Exception("Should throw IKE for dec w/o params");
} catch (InvalidKeyException ike) {
// expected
}
// Lastly, try encryption AND decryption w/ wrong type of parameters,
// e.g. IvParameterSpec
try {
c.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
throw new Exception("Should throw IAPE");
} catch (InvalidAlgorithmParameterException iape) {
// expected
}
try {
c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
throw new Exception("Should throw IAPE");
} catch (InvalidAlgorithmParameterException iape) {
// expected
}
System.out.println("Test Passed!");
}
public static void main (String[] args) throws Exception {
TestGCMKeyAndIvCheck t = new TestGCMKeyAndIvCheck();
t.test();
}
}

View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2025, Google LLC. 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.
*
* 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.
*/
/*
* @test
* @bug 8371864
* @run main/othervm/timeout=600 TestGCMSplitBound
* @requires (os.simpleArch == "x64" & (vm.cpu.features ~= ".*avx2.*" |
* vm.cpu.features ~= ".*avx512.*"))
* @summary Test GaloisCounterMode.implGCMCrypt0 AVX512/AVX2 intrinsics.
*/
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.time.Duration;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class TestGCMSplitBound {
static final SecureRandom SECURE_RANDOM = newDefaultSecureRandom();
private static SecureRandom newDefaultSecureRandom() {
SecureRandom retval = new SecureRandom();
retval.nextLong(); // force seeding
return retval;
}
private static byte[] randBytes(int size) {
byte[] rand = new byte[size];
SECURE_RANDOM.nextBytes(rand);
return rand;
}
private static final int IV_SIZE_IN_BYTES = 12;
private static final int TAG_SIZE_IN_BYTES = 16;
private Cipher getCipher(final byte[] key, final byte[] aad,
final byte[] nonce, int mode)
throws Exception {
SecretKey keySpec = new SecretKeySpec(key, "AES");
AlgorithmParameterSpec params =
new GCMParameterSpec(8 * TAG_SIZE_IN_BYTES, nonce, 0, nonce.length);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(mode, keySpec, params);
if (aad != null && aad.length != 0) {
cipher.updateAAD(aad);
}
return cipher;
}
private byte[] gcmEncrypt(final byte[] key, final byte[] plaintext,
final byte[] aad)
throws Exception {
byte[] nonce = randBytes(IV_SIZE_IN_BYTES);
Cipher cipher = getCipher(key, aad, nonce, Cipher.ENCRYPT_MODE);
int outputSize = cipher.getOutputSize(plaintext.length);
int len = IV_SIZE_IN_BYTES + outputSize;
byte[] output = new byte[len];
System.arraycopy(nonce, 0, output, 0, IV_SIZE_IN_BYTES);
cipher.doFinal(plaintext, 0, plaintext.length, output,
IV_SIZE_IN_BYTES);
return output;
}
private byte[] gcmDecrypt(final byte[] key, final byte[] ciphertext,
final byte[] aad)
throws Exception {
byte[] nonce = new byte[IV_SIZE_IN_BYTES];
System.arraycopy(ciphertext, 0, nonce, 0, IV_SIZE_IN_BYTES);
Cipher cipher = getCipher(key, aad, nonce, Cipher.DECRYPT_MODE);
return cipher.doFinal(ciphertext, IV_SIZE_IN_BYTES,
ciphertext.length - IV_SIZE_IN_BYTES);
}
// x86-64 parallel intrinsic data size
private static final int PARALLEL_LEN = 512;
// max data size for x86-64 intrinsic
private static final int SPLIT_LEN = 1048576; // 1MB
private void encryptAndDecrypt(byte[] key, byte[] aad, byte[] message,
int messageSize)
throws Exception {
byte[] ciphertext = gcmEncrypt(key, message, aad);
byte[] decrypted = gcmDecrypt(key, ciphertext, aad);
if (ciphertext == null) {
throw new RuntimeException("ciphertext is null");
}
if (Arrays.compare(decrypted, 0, messageSize,
message, 0, messageSize) != 0) {
throw new RuntimeException(
"Decrypted message is different from the original message");
}
}
private void run() throws Exception {
byte[] aad = randBytes(20);
byte[] key = randBytes(16);
// Force JIT.
for (int i = 0; i < 100000; i++) {
byte[] message = randBytes(PARALLEL_LEN);
encryptAndDecrypt(key, aad, message, PARALLEL_LEN);
}
for (int messageSize = SPLIT_LEN - 300; messageSize <= SPLIT_LEN + 300;
messageSize++) {
byte[] message = randBytes(messageSize);
try {
encryptAndDecrypt(key, aad, message, messageSize);
} catch (Exception e) {
throw new RuntimeException("Failed for messageSize "
+ Integer.toHexString(messageSize), e);
}
}
}
public static void main(String[] args) throws Exception {
TestGCMSplitBound test = new TestGCMSplitBound();
for (int i = 0; i < 3; i++) {
test.run();
}
}
}

View file

@ -0,0 +1,187 @@
/*
* Copyright (c) 2015, Red Hat, Inc.
* Copyright (c) 2015, Oracle, Inc.
* 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.
*
* 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.
*/
/*
* @test
* @bug 8069072
* @modules java.base/com.sun.crypto.provider:open
* @summary Test vectors for com.sun.crypto.provider.GHASH.
*
* Single iteration to verify software-only GHASH algorithm.
* @run main TestGHASH
*
* Multi-iteration to verify test intrinsics GHASH, if available.
* Many iterations are needed so we are sure hotspot will use intrinsic
* @run main TestGHASH -n 10000
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
public class TestGHASH {
private final Constructor<?> GHASH;
private final Method UPDATE;
private final Method DIGEST;
TestGHASH(String className) throws Exception {
Class<?> cls = Class.forName(className);
GHASH = cls.getDeclaredConstructor(byte[].class);
GHASH.setAccessible(true);
UPDATE = cls.getDeclaredMethod("update", byte[].class);
UPDATE.setAccessible(true);
DIGEST = cls.getDeclaredMethod("digest");
DIGEST.setAccessible(true);
}
private Object newGHASH(byte[] H) throws Exception {
return GHASH.newInstance(H);
}
private void updateGHASH(Object hash, byte[] data)
throws Exception {
UPDATE.invoke(hash, data);
}
private byte[] digestGHASH(Object hash) throws Exception {
return (byte[]) DIGEST.invoke(hash);
}
private static final String HEX_DIGITS = "0123456789abcdef";
private static String hex(byte[] bs) {
StringBuilder sb = new StringBuilder(2 * bs.length);
for (byte b : bs) {
sb.append(HEX_DIGITS.charAt((b >> 4) & 0xF));
sb.append(HEX_DIGITS.charAt(b & 0xF));
}
return sb.toString();
}
private static byte[] bytes(String hex) {
if ((hex.length() & 1) != 0) {
throw new AssertionError();
}
byte[] result = new byte[hex.length() / 2];
for (int i = 0; i < result.length; ++i) {
int a = HEX_DIGITS.indexOf(hex.charAt(2 * i));
int b = HEX_DIGITS.indexOf(hex.charAt(2 * i + 1));
if ((a | b) < 0) {
if (a < 0) {
throw new AssertionError(
"bad character " + (int) hex.charAt(2 * i));
}
throw new AssertionError(
"bad character " + (int) hex.charAt(2 * i + 1));
}
result[i] = (byte) ((a << 4) | b);
}
return result;
}
private static byte[] bytes(long L0, long L1) {
return ByteBuffer.allocate(16)
.putLong(L0)
.putLong(L1)
.array();
}
private void check(int testCase, String H, String A,
String C, String expected) throws Exception {
int lenA = A.length() * 4;
while ((A.length() % 32) != 0) {
A += '0';
}
int lenC = C.length() * 4;
while ((C.length() % 32) != 0) {
C += '0';
}
Object hash = newGHASH(bytes(H));
updateGHASH(hash, bytes(A));
updateGHASH(hash, bytes(C));
updateGHASH(hash, bytes(lenA, lenC));
byte[] digest = digestGHASH(hash);
String actual = hex(digest);
if (!expected.equals(actual)) {
throw new AssertionError(String.format("%d: expected %s, got %s",
testCase, expected, actual));
}
}
public static void main(String[] args) throws Exception {
TestGHASH test;
String test_class = "com.sun.crypto.provider.GHASH";
int i = 0;
int num_of_loops = 1;
while (args.length > i) {
if (args[i].compareTo("-c") == 0) {
test_class = args[++i];
} else if (args[i].compareTo("-n") == 0) {
num_of_loops = Integer.parseInt(args[++i]);
}
i++;
}
System.out.println("Running " + num_of_loops + " iterations.");
test = new TestGHASH(test_class);
i = 0;
while (num_of_loops > i) {
// Test vectors from David A. McGrew, John Viega,
// "The Galois/Counter Mode of Operation (GCM)", 2005.
// <http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf>
test.check(1, "66e94bd4ef8a2c3b884cfa59ca342b2e", "", "",
"00000000000000000000000000000000");
test.check(2,
"66e94bd4ef8a2c3b884cfa59ca342b2e", "",
"0388dace60b6a392f328c2b971b2fe78",
"f38cbb1ad69223dcc3457ae5b6b0f885");
test.check(3,
"b83b533708bf535d0aa6e52980d53b78", "",
"42831ec2217774244b7221b784d0d49c" +
"e3aa212f2c02a4e035c17e2329aca12e" +
"21d514b25466931c7d8f6a5aac84aa05" +
"1ba30b396a0aac973d58e091473f5985",
"7f1b32b81b820d02614f8895ac1d4eac");
test.check(4,
"b83b533708bf535d0aa6e52980d53b78",
"feedfacedeadbeeffeedfacedeadbeef" + "abaddad2",
"42831ec2217774244b7221b784d0d49c" +
"e3aa212f2c02a4e035c17e2329aca12e" +
"21d514b25466931c7d8f6a5aac84aa05" +
"1ba30b396a0aac973d58e091",
"698e57f70e6ecc7fd9463b7260a9ae5f");
test.check(5, "b83b533708bf535d0aa6e52980d53b78",
"feedfacedeadbeeffeedfacedeadbeef" + "abaddad2",
"61353b4c2806934a777ff51fa22a4755" +
"699b2a714fcdc6f83766e5f97b6c7423" +
"73806900e49f24b22b097544d4896b42" +
"4989b5e1ebac0f07c23f4598",
"df586bb4c249b92cb6922877e444d37b");
i++;
}
}
}

View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2003, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4921443
* @summary Ensure ISO10126Padding works correctly.
* @author Valerie Peng
* @key randomness
*/
import java.util.Arrays;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.Provider;
public class TestISO10126Padding {
private static final String ALGO = "AES";
private static final String TRANS = "AES/ECB";
private static final int KEYSIZE = 16; // in bytes
private SecretKey key;
private TestISO10126Padding() throws Exception {
// setup
KeyGenerator kg = KeyGenerator.getInstance(ALGO,
System.getProperty("test.provider.name", "SunJCE"));
kg.init(KEYSIZE*8);
key = kg.generateKey();
}
private void runTest(int dataLength) throws Exception {
// setup
byte[] data = new byte[dataLength];
new SecureRandom().nextBytes(data);
System.out.println("Testing data length: " + dataLength);
// TEST#1 --
// generate the cipher text using manually-supplied
// XML Encryption padding
Cipher ci = Cipher.getInstance(TRANS + "/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
ci.init(Cipher.ENCRYPT_MODE, key);
byte[] paddedData = new byte[ci.getBlockSize()];
System.arraycopy(data, 0, paddedData, 0, data.length);
int padValue = paddedData.length - data.length;
paddedData[paddedData.length-1] = (byte) padValue;
byte[] cipherText = ci.doFinal(paddedData);
// decrypt using ISO10126Padding
ci = Cipher.getInstance(TRANS + "/ISO10126Padding",
System.getProperty("test.provider.name", "SunJCE"));
ci.init(Cipher.DECRYPT_MODE, key);
byte[] recovered = ci.doFinal(cipherText);
if (!Arrays.equals(data, recovered)) {
throw new Exception("TEST#1: decryption failed");
}
// TEST#2 --
// generate the cipher text using ISO10126Padding
ci = Cipher.getInstance(TRANS + "/ISO10126Padding",
System.getProperty("test.provider.name", "SunJCE"));
ci.init(Cipher.ENCRYPT_MODE, key);
cipherText = ci.doFinal(data);
// decrypt using ISO10126Padding
ci.init(Cipher.DECRYPT_MODE, key);
recovered = ci.doFinal(cipherText);
if (!Arrays.equals(data, recovered)) {
throw new Exception("TEST#2: decryption failed");
}
}
public static void main(String[] argv) throws Exception {
TestISO10126Padding test = new TestISO10126Padding();
for (int i = 0; i<16; i++) {
test.runTest(i);
}
System.out.println("Test Passed");
}
}

View file

@ -0,0 +1,128 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4635086
* @library ../UTIL
* @build TestUtil
* @run main TestKATForECB_IV
* @summary Known Answer Test for AES cipher with ECB mode
* @author Valerie Peng
*/
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.math.*;
import java.util.*;
public class TestKATForECB_IV
{
private static final String ALGO = "AES";
private static final String MODE = "ECB";
private static final String PADDING = "NoPadding";
//ecb-iv.txt
private static String[] PTS = {
"000102030405060708090A0B0C0D0E0F",
"000102030405060708090A0B0C0D0E0F",
"000102030405060708090A0B0C0D0E0F"
};
private static String[] CTS = {
"0A940BB5416EF045F1C39458C653EA5A",
"0060BFFE46834BB8DA5CF9A61FF220AE",
"5A6E045708FB7196F02E553D02C3A692"
};
private static String[] KEYS = {
"000102030405060708090A0B0C0D0E0F",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"
};
private static SecretKey constructAESKey(String s) throws Exception {
int len = s.length()/2;
if ((len != 16) && (len != 24) && (len != 32)) {
throw new IllegalArgumentException("Wrong Key Length: " + len);
}
byte[] rawKeyValue = constructByteArray(s);
SecretKeySpec key = new SecretKeySpec(rawKeyValue, "AES");
return key;
}
private static byte[] constructByteArray(String s) {
int len = s.length()/2;
byte[] tempValue = new byte[len];
for (int i = 0; i < len; i++) {
tempValue[i] = Integer.valueOf(s.substring(2*i, 2*i+2),
16).byteValue();
}
return tempValue;
}
public boolean execute() throws Exception {
String transformation = ALGO+"/"+MODE+"/"+PADDING;
Cipher c = Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
for (int i=0; i<KEYS.length; i++) {
SecretKey aesKey = constructAESKey(KEYS[i]);
if (aesKey.getEncoded().length*8 >
Cipher.getMaxAllowedKeyLength(transformation)) {
// skip if this key length is larger than what's
// configured in the jce jurisdiction policy files
continue;
}
try {
c.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] plainText = constructByteArray(PTS[i]);
byte[] cipherText = c.doFinal(plainText);
byte[] answer = constructByteArray(CTS[i]);
if (!Arrays.equals(cipherText, answer)) {
throw new Exception((i+1) + "th known answer test failed for encryption");
}
c.init(Cipher.DECRYPT_MODE, aesKey);
byte[] recoveredText = c.doFinal(answer);
if (!Arrays.equals(recoveredText, plainText)) {
throw new Exception("known answer test failed for decryption");
}
System.out.println("Finished KAT for " + aesKey.getEncoded().length + "-byte key");
} catch (SecurityException se) {
TestUtil.handleSE(se);
}
}
// passed all tests...hooray!
return true;
}
public static void main (String[] args) throws Exception {
TestKATForECB_IV test = new TestKATForECB_IV();
String testName = test.getClass().getName() + "[" + ALGO +
"/" + MODE + "/" + PADDING + "]";
if (test.execute()) {
System.out.println(testName + ": Passed!");
}
}
}

View file

@ -0,0 +1,756 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4635086
* @library ../UTIL
* @build TestUtil
* @run main TestKATForECB_VK
* @summary Known Answer Test for AES cipher with ECB mode
* @author Valerie Peng
*/
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.math.*;
import java.util.*;
public class TestKATForECB_VK
{
private static final String ALGO = "AES";
private static final String MODE = "ECB";
private static final String PADDING = "NoPadding";
//ecb-vk.txt
private static byte[] PT = new byte[16];
private static String[][] CTS = {
// Cipher Texts for 128-bit key
{
"0EDD33D3C621E546455BD8BA1418BEC8",
"C0CC0C5DA5BD63ACD44A80774FAD5222",
"2F0B4B71BC77851B9CA56D42EB8FF080",
"6B1E2FFFE8A114009D8FE22F6DB5F876",
"9AA042C315F94CBB97B62202F83358F5",
"DBE01DE67E346A800C4C4B4880311DE4",
"C117D2238D53836ACD92DDCDB85D6A21",
"DC0ED85DF9611ABB7249CDD168C5467E",
"807D678FFF1F56FA92DE3381904842F2",
"0E53B3FCAD8E4B130EF73AEB957FB402",
"969FFD3B7C35439417E7BDE923035D65",
"A99B512C19CA56070491166A1503BF15",
"6E9985252126EE344D26AE369D2327E3",
"B85F4809F904C275491FCDCD1610387E",
"ED365B8D7D20C1F5D53FB94DD211DF7B",
"B3A575E86A8DB4A7135D604C43304896",
"89704BCB8E69F846259EB0ACCBC7F8A2",
"C56EE7C92197861F10D7A92B90882055",
"92F296F6846E0EAF9422A5A24A08B069",
"E67E32BB8F11DEB8699318BEE9E91A60",
"B08EEF85EAF626DD91B65C4C3A97D92B",
"661083A6ADDCE79BB4E0859AB5538013",
"55DFE2941E0EB10AFC0B333BD34DE1FE",
"6BFE5945E715C9662609770F8846087A",
"79848E9C30C2F8CDA8B325F7FED2B139",
"7A713A53B99FEF34AC04DEEF80965BD0",
"18144A2B46620D32C3C32CE52D49257F",
"872E827C70887C80749F7B8BB1847C7E",
"6B86C6A4FE6A60C59B1A3102F8DE49F3",
"9848BB3DFDF6F532F094679A4C231A20",
"925AD528E852E329B2091CD3F1C2BCEE",
"80DF436544B0DD596722E46792A40CD8",
"525DAF18F93E83E1E74BBBDDE4263BBA",
"F65C9D2EE485D24701FFA3313B9D5BE6",
"E4FC8D8BCA06425BDF94AFA40FCC14BA",
"A53F0A5CA1E4E6440BB975FF320DE6F8",
"D55313B9394080462E87E02899B553F0",
"34A71D761F71BCD344384C7F97D27906",
"233F3D819599612EBC89580245C996A8",
"B4F1374E5268DBCB676E447529E53F89",
"0816BD27861D2BA891D1044E39951E96",
"F3BE9EA3F10C73CA64FDE5DB13A951D1",
"2448086A8106FBD03048DDF857D3F1C8",
"670756E65BEC8B68F03D77CDCDCE7B91",
"EF968CF0D36FD6C6EFFD225F6FB44CA9",
"2E8767157922E3826DDCEC1B0CC1E105",
"78CE7EEC670E45A967BAB17E26A1AD36",
"3C5CEE825655F098F6E81A2F417DA3FB",
"67BFDB431DCE1292200BC6F5207ADB12",
"7540FD38E447C0779228548747843A6F",
"B85E513301F8A936EA9EC8A21A85B5E6",
"04C67DBF16C11427D507A455DE2C9BC5",
"03F75EB8959E55079CFFB4FF149A37B6",
"74550287F666C63BB9BC7838433434B0",
"7D537200195EBC3AEFD1EAAB1C385221",
"CE24E4D40C68A82B535CBD3C8E21652A",
"AB20072405AA8FC40265C6F1F3DC8BC0",
"6CFD2CF688F566B093F67B9B3839E80A",
"BD95977E6B7239D407A012C5544BF584",
"DF9C0130AC77E7C72C997F587B46DBE0",
"E7F1B82CADC53A648798945B34EFEFF2",
"932C6DBF69255CF13EDCDB72233ACEA3",
"5C76002BC7206560EFE550C80B8F12CC",
"F6B7BDD1CAEEBAB574683893C4475484",
"A920E37CC6DC6B31DA8C0169569F5034",
"919380ECD9C778BC513148B0C28D65FD",
"EE67308DD3F2D9E6C2170755E5784BE1",
"3CC73E53B85609023A05E149B223AE09",
"983E8AF7CF05EBB28D71EB841C9406E6",
"0F3099B2D31FA5299EE5BF43193287FC",
"B763D84F38C27FE6931DCEB6715D4DB6",
"5AE3C9B0E3CC29C0C61565CD01F8A248",
"F58083572CD90981958565D48D2DEE25",
"7E6255EEF8F70C0EF10337AAB1CCCEF8",
"AAD4BAC34DB22821841CE2F631961902",
"D7431C0409BB1441BA9C6858DC7D4E81",
"EF9298C65E339F6E801A59C626456993",
"53FE29F68FF541ABC3F0EF3350B72F7E",
"F6BBA5C10DB02529E2C2DA3FB582CC14",
"E4239AA37FC531A386DAD1126FC0E9CD",
"8F7758F857D15BBE7BFD0E416404C365",
"D273EB57C687BCD1B4EA7218A509E7B8",
"65D64F8D76E8B3423FA25C4EB58A210A",
"623D802B4EC450D66A16625702FCDBE0",
"7496460CB28E5791BAEAF9B68FB00022",
"34EA600F18BB0694B41681A49D510C1D",
"5F8FF0D47D5766D29B5D6E8F46423BD8",
"225F9286C5928BF09F84D3F93F541959",
"B21E90D25DF383416A5F072CEBEB1FFB",
"4AEFCDA089318125453EB9E8EB5E492E",
"4D3E75C6CD40EC4869BC85158591ADB8",
"63A8B904405436A1B99D7751866771B7",
"64F0DAAE47529199792EAE172BA53293",
"C3EEF84BEA18225D515A8C852A9047EE",
"A44AC422B47D47B81AF73B3E9AC9596E",
"D16E04A8FBC435094F8D53ADF25F5084",
"EF13DC34BAB03E124EEAD8B6BF44B532",
"D94799075C24DCC067AF0D392049250D",
"14F431771EDDCE4764C21A2254B5E3C8",
"7039329F36F2ED682B02991F28D64679",
"124EE24EDE5551639DB8B8B941F6141D",
"C2852879A34D5184E478EC918B993FEE",
"86A806A3525B93E432053C9AB5ABBEDF",
"C1609BF5A4F07E37C17A36366EC23ECC",
"7E81E7CB92159A51FFCEA331B1E8EA53",
"37A7BE002856C5A59A6E03EAFCE7729A",
"BDF98A5A4F91E890C9A1D1E5FAAB138F",
"4E96ACB66E051F2BC739CC3D3E34A26B",
"EE996CDD120EB86E21ECFA49E8E1FCF1",
"61B9E6B579DBF6070C351A1440DD85FF",
"AC369E484316440B40DFC83AA96E28E7",
"0A2D16DE985C76D45C579C1159413BBE",
"DA3FDC38DA1D374FA4802CDA1A1C6B0F",
"B842523D4C41C2211AFE43A5800ADCE3",
"9E2CDA90D8E992DBA6C73D8229567192",
"D49583B781D9E20F5BE101415957FC49",
"EF09DA5C12B376E458B9B8670032498E",
"A96BE0463DA774461A5E1D5A9DD1AC10",
"32CEE3341060790D2D4B1362EF397090",
"21CEA416A3D3359D2C4D58FB6A035F06",
"172AEAB3D507678ECAF455C12587ADB7",
"B6F897941EF8EBFF9FE80A567EF38478",
"A9723259D94A7DC662FB0C782CA3F1DD",
"2F91C984B9A4839F30001B9F430493B4",
"0472406345A610B048CB99EE0EF3FA0F",
"F5F39086646F8C05ED16EFA4B617957C",
"26D50F485A30408D5AF47A5736292450",
"0545AAD56DA2A97C3663D1432A3D1C84"
},
// Cipher Texts for 192-bit key
{
"DE885DC87F5A92594082D02CC1E1B42C",
"C749194F94673F9DD2AA1932849630C1",
"0CEF643313912934D310297B90F56ECC",
"C4495D39D4A553B225FBA02A7B1B87E1",
"636D10B1A0BCAB541D680A7970ADC830",
"07CF045786BD6AFCC147D99E45A901A7",
"6A8E3F425A7599348F95398448827976",
"5518276836148A00D91089A20D8BFF57",
"F267E07B5E87E3BC20B969C61D4FCB06",
"5A1CDE69571D401BFCD20DEBADA2212C",
"70A9057263254701D12ADD7D74CD509E",
"35713A7E108031279388A33A0FE2E190",
"E74EDE82B1254714F0C7B4B243108655",
"39272E3100FAA37B55B862320D1B3EB3",
"6D6E24C659FC5AEF712F77BCA19C9DD0",
"76D18212F972370D3CC2C6C372C6CF2F",
"B21A1F0BAE39E55C7594ED570A7783EA",
"77DE202111895AC48DD1C974B358B458",
"67810B311969012AAF7B504FFAF39FD1",
"C22EA2344D3E9417A6BA07843E713AEA",
"C79CAF4B97BEE0BD0630AB354539D653",
"135FD1AF761D9AE23DF4AA6B86760DB4",
"D4659D0B06ACD4D56AB8D11A16FD83B9",
"F7D270028FC188E4E4F35A4AAA25D4D4",
"345CAE5A8C9620A9913D5473985852FF",
"4E8980ADDE60B0E42C0B287FEA41E729",
"F11B6D74E1F15155633DC39743C1A527",
"9C87916C0180064F9D3179C6F5DD8C35",
"71AB186BCAEA518E461D4F7FAD230E6A",
"C4A31BBC3DAAF742F9141C2A5001A49C",
"E7C47B7B1D40F182A8928C8A55671D07",
"8E17F294B28FA373C6249538868A7EEF",
"754404096A5CBC08AF09491BE249141A",
"101CB56E55F05D86369B6D1069204F0A",
"73F19BB6604205C6EE227B9759791E41",
"6270C0028F0D136C37A56B2CB64D24D6",
"A3BF7C2C38D1114A087ECF212E694346",
"49CABFF2CEF7D9F95F5EFB1F7A1A7DDE",
"EC7F8A47CC59B849469255AD49F62752",
"68FAE55A13EFAF9B07B3552A8A0DC9D1",
"211E6B19C69FAEF481F64F24099CDA65",
"DBB918C75BC5732416F79FB0C8EE4C5C",
"98D494E5D963A6C8B92536D3EC35E3FD",
"C9A873404D403D6F074190851D67781A",
"073AEF4A7C77D921928CB0DD9D27CAE7",
"89BDE25CEE36FDE769A10E52298CF90F",
"26D0842D37EAD38557C65E0A5E5F122E",
"F8294BA375AF46B3F22905BBAFFAB107",
"2AD63EB4D0D43813B979CF72B35BDB94",
"7710C171EE0F4EFA39BE4C995180181D",
"C0CB2B40DBA7BE8C0698FAE1E4B80FF8",
"97970E505194622FD955CA1B80B784E9",
"7CB1824B29F850900DF2CAD9CF04C1CF",
"FDF4F036BB988E42F2F62DE63FE19A64",
"08908CFE2C82606B2C15DF61B75CF3E2",
"B3AA689EF2D07FF365ACB9ADBA2AF07A",
"F2672CD8EAA3B98776660D0263656F5C",
"5BDEAC00E986687B9E1D94A0DA7BF452",
"E6D57BD66EA1627363EE0C4B711B0B21",
"03730DD6ACB4AD9996A63BE7765EC06F",
"A470E361AA5437B2BE8586D2F78DE582",
"7567FEEFA559911FD479670246B484E3",
"29829DEA15A4E7A4C049045E7B106E29",
"A407834C3D89D48A2CB7A152208FA4ED",
"68F948053F78FEF0D8F9FE7EF3A89819",
"B605174CAB13AD8FE3B20DA3AE7B0234",
"CCAB8F0AEBFF032893996D383CBFDBFA",
"AF14BB8428C9730B7DC17B6C1CBEBCC8",
"5A41A21332040877EB7B89E8E80D19FE",
"AC1BA52EFCDDE368B1596F2F0AD893A0",
"41B890E31B9045E6ECDC1BC3F2DB9BCC",
"4D54A549728E55B19A23660424A0F146",
"A917581F41C47C7DDCFFD5285E2D6A61",
"604DF24BA6099B93A7405A524D764FCB",
"78D9D156F28B190E232D1B7AE7FC730A",
"5A12C39E442CD7F27B3CD77F5D029582",
"FF2BF2F47CF7B0F28EE25AF95DBF790D",
"1863BB7D193BDA39DF090659EB8AE48B",
"38178F2FB4CFCF31E87E1ABCDC023EB5",
"F5B13DC690CC0D541C6BA533023DC8C9",
"48EC05238D7375D126DC9D08884D4827",
"ACD0D81139691B310B92A6E377BACC87",
"9A4AA43578B55CE9CC178F0D2E162C79",
"08AD94BC737DB3C87D49B9E01B720D81",
"3BCFB2D5D210E8332900C5991D551A2A",
"C5F0C6B9397ACB29635CE1A0DA2D8D96",
"844A29EFC693E2FA9900F87FBF5DCD5F",
"5126A1C41051FEA158BE41200E1EA59D",
"302123CA7B4F46D667FFFB0EB6AA7703",
"A9D16BCE7DB5C024277709EE2A88D91A",
"F013C5EC123A26CFC34B598C992A996B",
"E38A825CD971A1D2E56FB1DBA248F2A8",
"6E701773C0311E0BD4C5A097406D22B3",
"754262CEF0C64BE4C3E67C35ABE439F7",
"C9C2D4C47DF7D55CFA0EE5F1FE5070F4",
"6AB4BEA85B172573D8BD2D5F4329F13D",
"11F03EF28E2CC9AE5165C587F7396C8C",
"0682F2EB1A68BAC7949922C630DD27FA",
"ABB0FEC0413D659AFE8E3DCF6BA873BB",
"FE86A32E19F805D6569B2EFADD9C92AA",
"E434E472275D1837D3D717F2EECC88C3",
"74E57DCD12A21D26EF8ADAFA5E60469A",
"C275429D6DAD45DDD423FA63C816A9C1",
"7F6EC1A9AE729E86F7744AED4B8F4F07",
"48B5A71AB9292BD4F9E608EF102636B2",
"076FB95D5F536C78CBED3181BCCF3CF1",
"BFA76BEA1E684FD3BF9256119EE0BC0F",
"7D395923D56577F3FF8670998F8C4A71",
"BA02C986E529AC18A882C34BA389625F",
"3DFCF2D882AFE75D3A191193013A84B5",
"FAD1FDE1D0241784B63080D2C74D236C",
"7D6C80D39E41F007A14FB9CD2B2C15CD",
"7975F401FC10637BB33EA2DB058FF6EC",
"657983865C55A818F02B7FCD52ED7E99",
"B32BEB1776F9827FF4C3AC9997E84B20",
"2AE2C7C374F0A41E3D46DBC3E66BB59F",
"4D835E4ABDD4BDC6B88316A6E931A07F",
"E07EFABFF1C353F7384EBB87B435A3F3",
"ED3088DC3FAF89AD87B4356FF1BB09C2",
"4324D01140C156FC898C2E32BA03FB05",
"BE15D016FACB5BAFBC24FA9289132166",
"AC9B7048EDB1ACF4D97A5B0B3F50884B",
"448BECE1F86C7845DFA9A4BB2A016FB3",
"10DD445E87686EB46EA9B1ABC49257F0",
"B7FCCF7659FA756D4B7303EEA6C07458",
"289117115CA3513BAA7640B1004872C2",
"57CB42F7EE7186051F50B93FFA7B35BF",
"F2741BFBFB81663B9136802FB9C3126A",
"E32DDDC5C7398C096E3BD535B31DB5CE",
"81D3C204E608AF9CC713EAEBCB72433F",
"D4DEEF4BFC36AAA579496E6935F8F98E",
"C356DB082B97802B038571C392C5C8F6",
"A3919ECD4861845F2527B77F06AC6A4E",
"A53858E17A2F802A20E40D44494FFDA0",
"5D989E122B78C758921EDBEEB827F0C0",
"4B1C0C8F9E7830CC3C4BE7BD226FA8DE",
"82C40C5FD897FBCA7B899C70713573A1",
"ED13EE2D45E00F75CCDB51EA8E3E36AD",
"F121799EEFE8432423176A3CCF6462BB",
"4FA0C06F07997E98271DD86F7B355C50",
"849EB364B4E81D058649DC5B1BF029B9",
"F48F9E0DE8DE7AD944A207809335D9B1",
"E59E9205B5A81A4FD26DFCF308966022",
"3A91A1BE14AAE9ED700BDF9D70018804",
"8ABAD78DCB79A48D79070E7DA89664EC",
"B68377D98AAE6044938A7457F6C649D9",
"E4E1275C42F5F1B63D662C099D6CE33D",
"7DEF32A34C6BE668F17DA1BB193B06EF",
"78B6000CC3D30CB3A74B68D0EDBD2B53",
"0A47531DE88DD8AE5C23EAE4F7D1F2D5",
"667B24E8000CF68231EC484581D922E5",
"39DAA5EBD4AACAE130E9C33236C52024",
"E3C88760B3CB21360668A63E55BB45D1",
"F131EE903C1CDB49D416866FD5D8DE51",
"7A1916135B0447CF4033FC13047A583A",
"F7D55FB27991143DCDFA90DDF0424FCB",
"EA93E7D1CA1111DBD8F7EC111A848C0C",
"2A689E39DFD3CBCBE221326E95888779",
"C1CE399CA762318AC2C40D1928B4C57D",
"D43FB6F2B2879C8BFAF0092DA2CA63ED",
"224563E617158DF97650AF5D130E78A5",
"6562FDF6833B7C4F7484AE6EBCC243DD",
"93D58BA7BED22615D661D002885A7457",
"9A0EF559003AD9E52D3E09ED3C1D3320",
"96BAF5A7DC6F3DD27EB4C717A85D261C",
"B8762E06884900E8452293190E19CCDB",
"785416A22BD63CBABF4B1789355197D3",
"A0D20CE1489BAA69A3612DCE90F7ABF6",
"700244E93DC94230CC607FFBA0E48F32",
"85329E476829F872A2B4A7E59F91FF2D",
"E4219B4935D988DB719B8B8B2B53D247",
"6ACDD04FD13D4DB4409FE8DD13FD737B",
"9EB7A670AB59E15BE582378701C1EC14",
"29DF2D6935FE657763BC7A9F22D3D492",
"99303359D4A13AFDBE6C784028CE533A",
"FF5C70A6334545F33B9DBF7BEA0417CA",
"289F58A17E4C50EDA4269EFB3DF55815",
"EA35DCB416E9E1C2861D1682F062B5EB",
"3A47BF354BE775383C50B0C0A83E3A58",
"BF6C1DC069FB95D05D43B01D8206D66B",
"046D1D580D5898DA6595F32FD1F0C33D",
"5F57803B7B82A110F7E9855D6A546082",
"25336ECF34E7BE97862CDFF715FF05A8",
"ACBAA2A943D8078022D693890E8C4FEF",
"3947597879F6B58E4E2F0DF825A83A38",
"4EB8CC3335496130655BF3CA570A4FC0",
"BBDA7769AD1FDA425E18332D97868824",
"5E7532D22DDB0829A29C868198397154",
"E66DA67B630AB7AE3E682855E1A1698E",
"4D93800F671B48559A64D1EA030A590A",
"F33159FCC7D9AE30C062CD3B322AC764",
"8BAE4EFB70D33A9792EEA9BE70889D72"
},
// Cipher Texts for 256-bit key
{
"E35A6DCB19B201A01EBCFA8AA22B5759",
"5075C2405B76F22F553488CAE47CE90B",
"49DF95D844A0145A7DE01C91793302D3",
"E7396D778E940B8418A86120E5F421FE",
"05F535C36FCEDE4657BE37F4087DB1EF",
"D0C1DDDD10DA777C68AB36AF51F2C204",
"1C55FB811B5C6464C4E5DE1535A75514",
"52917F3AE957D5230D3A2AF57C7B5A71",
"C6E3D5501752DD5E9AEF086D6B45D705",
"A24A9C7AF1D9B1E17E1C9A3E711B3FA7",
"B881ECA724A6D43DBC6B96F6F59A0D20",
"EC524D9A24DFFF2A9639879B83B8E137",
"34C4F345F5466215A037F443635D6F75",
"5BA5055BEDB8895F672E29F2EB5A355D",
"B3F692AA3A435259EBBEF9B51AD1E08D",
"414FEB4376F2C64A5D2FBB2ED531BA7D",
"A20D519E3BCA3303F07E81719F61605E",
"A08D10E520AF811F45BD60A2DC0DC4B1",
"B06893A8C563C430E6F3858826EFBBE4",
"0FFEE26AE2D3929C6BD9C6BEDFF84409",
"4D0F5E906ED77801FC0EF53EDC5F9E2B",
"8B6EC00119AD8B026DCE56EA7DEFE930",
"69026591D43363EE9D83B5007F0B484E",
"27135D86950C6A2F86872706279A4761",
"35E6DB8723F281DA410C3AC8535ED77C",
"57427CF214B8C28E4BBF487CCB8D0E09",
"6DF01BF56E5131AC87F96E99CAB86367",
"3856C5B55790B768BBF7D43031579BCF",
"1E6ED8FB7C15BC4D2F63BA7037ED44D0",
"E1B2ED6CD8D93D455534E401156D4BCF",
"EFBCCA5BDFDAD10E875F02336212CE36",
"0B777F02FD18DCE2646DCFE868DFAFAD",
"C8A104B5693D1B14F5BF1F10100BF508",
"4CCE6615244AFCB38408FECE219962EA",
"F99E7845D3A255B394C9C050CBA258B1",
"B4AFBB787F9BCFB7B55FDF447F611295",
"AE1C426A697FAF2808B7EF6ADDB5C020",
"7572F92811A85B9BDD38DEAD9945BCAE",
"71BC7AA46E43FB95A181527D9F6A360F",
"5542EF2923066F1EC8F546DD0D8E7CA8",
"6B92317C7D623790B748FDD7EFC42422",
"0FE7C097E899C71EF045360F8D6C25CF",
"4ECE7EE107D0264D04693151C25B9DF6",
"FD6AE687CBFCA9E301045888D3BB9605",
"476B579C8556C7254424902CC1D6D36E",
"4133CBCDFDD6B8860A1FC18665D6D71B",
"3B36EC2664798C108B816812C65DFDC7",
"364E20A234FEA385D48DC5A09C9E70CF",
"4A4BA25969DE3F5EE5642C71AAD0EFD1",
"E42CBAAE43297F67A76C1C501BB79E36",
"23CEDEDA4C15B4C037E8C61492217937",
"A1719147A1F4A1A1180BD16E8593DCDE",
"AB82337E9FB0EC60D1F25A1D0014192C",
"74BF2D8FC5A8388DF1A3A4D7D33FC164",
"D5B493317E6FBC6FFFD664B3C491368A",
"BA767381586DA56A2A8D503D5F7ADA0B",
"E8E6BC57DFE9CCADB0DECABF4E5CF91F",
"3C8E5A5CDC9CEED90815D1F84BB2998C",
"283843020BA38F056001B2FD585F7CC9",
"D8ADC7426F623ECE8741A70621D28870",
"D7C5C215592D06F00E6A80DA69A28EA9",
"52CF6FA433C3C870CAC70190358F7F16",
"F63D442A584DA71786ADEC9F3346DF75",
"549078F4B0CA7079B45F9A5ADAFAFD99",
"F2A5986EE4E9984BE2BAFB79EA8152FA",
"8A74535017B4DB2776668A1FAE64384C",
"E613342F57A97FD95DC088711A5D0ECD",
"3FFAEBF6B22CF1DC82AE17CD48175B01",
"BAFD52EFA15C248CCBF9757735E6B1CE",
"7AF94BC018D9DDD4539D2DD1C6F4000F",
"FE177AD61CA0FDB281086FBA8FE76803",
"74DBEA15E2E9285BAD163D7D534251B6",
"23DD21331B3A92F200FE56FF050FFE74",
"A69C5AA34AB20A858CAFA766EACED6D8",
"3F72BB4DF2A4F941A4A09CB78F04B97A",
"72CC43577E1FD5FD14622D24D97FCDCC",
"D83AF8EBE93E0B6B99CAFADE224937D1",
"44042329128D56CAA8D084C8BD769D1E",
"14102D72290DE4F2C430ADD1ED64BA1D",
"449124097B1ECD0AE7065206DF06F03C",
"D060A99F8CC153A42E11E5F97BD7584A",
"65605B3EA9261488D53E48602ADEA299",
"C5E5CAD7A208DE8EA6BE049EFE5C7346",
"4C280C46D2181646048DD5BC0C0831A5",
"5DD65CF37F2A0929559AABAFDA08E730",
"31F2335CAAF264172F69A693225E6D22",
"3E28B35F99A72662590DA96426DD377F",
"570F40F5D7B20441486578ED344343BE",
"C54308AD1C9E3B19F8B7417873045A8C",
"CBF335E39CE13ADE2B696179E8FD0CE1",
"9C2FBF422355D8293083D51F4A3C18A9",
"5ED8B5A31ECEFAB16C9AA6986DA67BCE",
"627815DCFC814ABC75900041B1DD7B59",
"9EF3E82A50A59F166260494F7A7F2CC3",
"878CD0D8D920888B5935D6C351128737",
"E44429474D6FC3084EB2A6B8B46AF754",
"EBAACF9641D54E1FB18D0A2BE4F19BE5",
"13B3BF497CEE780E123C7E193DEA3A01",
"6E8F381DE00A41161F0DF03B4155BFD4",
"35E4F29BBA2BAE01144910783C3FEF49",
"55B17BD66788CEAC366398A31F289FFB",
"11341F56C0D6D1008D28741DAA7679CE",
"4DF7253DF421D83358BDBE924745D98C",
"BAE2EE651116D93EDC8E83B5F3347BE1",
"F9721ABD06709157183AF3965A659D9D",
"19A1C252A613FE2860A4AE6D75CE6FA3",
"B5DDB2F5D9752C949FBDE3FFF5556C6E",
"81B044FCFFC78ECCFCD171AAD0405C66",
"C640566D3C06020EB2C42F1D62E56A9B",
"EA6C4BCF425291679FDFFD26A424FBCC",
"57F6901465D9440D9F15EE2CBA5A4090",
"FBCFA74CADC7406260F63D96C8AAB6B1",
"DFF4F096CEA211D4BBDACA033D0EC7D1",
"1EE5190D551F0F42F675227A381296A9",
"F98E1905012E580F097623C10B93054F",
"E7D43743D21DD3C9F168C86856558B9A",
"632A9DDA730DAB67593C5D08D8AC1059",
"E084317000715B9057BC9DE9F3AB6124",
"61F9EF33A0BB4E666C2ED99101919FAB",
"6DC1D68A11834657D46703C22578D59A",
"53AC1548863D3D16F1D4DC7242E05F2C",
"E82CD587A408306AD78CEAE0916B9F8C",
"0FD2D40EA6AD17A3A767F0A8600D6295",
"AD84CC8255ADB39DFCA23F92761AE7E9",
"F4F20CF7D51BEE7DA024A2B11A7ECA0B",
"5057691B85D9CE93A193214DB0A016B6",
"0F58C960876390BDEF4BB6BE95CAA1EE",
"9A3E66EEBC21BC0BD9430B341EF465FA",
"20415035F34B8BCBCB28ABF07F78F0D4",
"AC89FC7BA10479EBF10DE65BCEF89B3C",
"068FA75A30BE443171AF3F6FEB1A20D2",
"50E02F213246C525A8C27700CA34B502",
"227DA47D5A0906DB3AB042BB0A695FB6",
"8663AC30ED12514F1DE46777F4514BFC",
"A987D4BC12E1DE9F4B6DF43567C34A8B",
"6D5A0370F599ACA605F63B04E5143D0C",
"9809266E378B07B7AFDB3BAA97B7E442",
"8F753252B30CCCACE12D9A301F4D5090",
"032465F6C0CE34D41962F561692A1AFF",
"C50E9AD5BEB8F3B00821DD47FF8AC093",
"9C6FEA3D46268D54A6829B2AD25BB276",
"0FD8575E87706F561343D7B3A41E044A",
"BEE9BEB3739540D88CBCE77925F0A114",
"D24EAEE7FFFBAC3D6F26C2DCE0DCDE28",
"47771A90398FF0F7FA821C2F8F5E1398",
"4639741B6F84B135AD118C8249B64ED0",
"8EE5505EC85567697A3306F250A27720",
"7C8A19AC1AEFBC5E0119D91A5F05D4C2",
"5141B9B672E54773B672E3A6C424887B",
"B5A2D3CD206653C6402F34FB0AE3613D",
"0F5BD9408738231D114B0A82753279A3",
"FEF033FF4268EA487FC74C5E43A45338",
"A3EDC09DCD529B113910D904AD855581",
"AB8FBB6F27A0AC7C55B59FDD36B72F1C",
"EEA44D5ED4D769CC930CD83D8999EC46",
"6972276803AE9AA7C6F431AB10979C34",
"86DEAA9F39244101818178474D7DBDE9",
"88C6B466EA361D662D8D08CBF181F4FE",
"91AB2C6B7C63FF59F7CBEEBF91B20B95",
"2DFE6C146AD5B3D8C3C1718F13B48E01",
"C7CFF1623451711391A302EEC3584AAA",
"089FE845CC05011686C66019D18BE050",
"08C8410B9B427211A67124B0DCCEAD48",
"8D91592F5566085254784606334D7629",
"3298FEAAF2E1201D6299FF8846639C97",
"C497CB9F0BDFE0EFC8C2F3F90760AA72",
"2788AFD046E0309CBE4424690DA2AB89",
"E9891707F25EF29FEE372890D4258982",
"DB041D94A23D45D4D4DCED5A030CAF61",
"FFAFDBF0ECB18DF9EA02C27077448E6D",
"2DAAA42A7D0A1D3B0E4761D99CF2150A",
"3B7A54CB7CF30ABE263DD6ED5BFE8D63",
"EEFA090174C590C448A55D43648F534A",
"9E15798731ED42F43EA2740A691DA872",
"31FBD661540A5DEAAD1017CFD3909EC8",
"CDA9AE05F224140E28CB951721B44D6A",
"0C5BC512C60A1EAC3434EFB1A8FBB182",
"AA863610DEEEEB62D045E87EA30B59B5",
"6AC2448DE568D279C7EEBE1DF403920C",
"E2011E3D292B26888AE801215FD0CB40",
"E06F3E15EE3A61672D1C99BADE5B9DBE",
"BB7027F0548CF6712CEB4C7A4B28E178",
"061EC21FB70FADBDF87C3BD2AE23825B",
"4C21F26FE94ABBAC381352375314C3EB",
"F7CEE6DD99909C2B569EEDA61ED8942E",
"CE98C4A876C65E4CCB261EBB1D9DF7F5",
"A5491881CF833C3604ABC08044F402AC",
"A1BA16E64CCCB3087D57A768507B0BFC",
"D55951E202D2949EBD3BE43120C738BF",
"EBB8E43069E69F450EFEC65DCD52B7FD",
"2B292135663B4AA5ABFE9423D57E7EE9",
"E91BF974B3BE3AD966249D8655292A85",
"384365998EAA9562236CC58F6ADF9610",
"C2E997012AA3D4D8D359C9A947CBE69F",
"F49421204148BA213BE87E2D5C22B0BF",
"82ED0ED9953AA92E4DF30929CA65C00F",
"291EB1D11653C8479437C74A977F5106",
"BCB997B1939B8983ABD550D6025683E3",
"1FBA2592C6F489775CAADA71F9B983E9",
"969F66F217AF1A3DB9E41C1B29039824",
"A54BB7D6B17E423AC0A7744C19073CB8",
"B0AC6E6578D1021F47DCF9748A32EAD5",
"B87B361C3B7B194C77A4358D4669153E",
"46A133847F96EAA8282A799DC8899D58",
"2265EC3A9F2D5C9547A091CC8CFB18EA",
"54CBF3A6FC4FE56D426117AA1FFD1DDE",
"5312877CCEAB6CFB0905394A370A8003",
"7190BD6EC613FE38B84ECFE28F702FE4",
"D1FA5B9CA89A43B04C05F0EF29EF68CD",
"808285751548ED934FD1056D2D9AE8BA",
"2758DEF3E7B95A9AE89777BE64D5A6CF",
"07D81F87DB3E0ACC82B01E08FB22F3C1",
"8DA250E5553D650711A75EE1CB4FD1C7",
"A93D946BD0E87F32719DF5F158CEE669",
"03945236EC2A4D4EAF30B8ABEB54330D",
"11CC35301F24B79DDE31AEA2D1354F88",
"E73715B3E8D9A290F44AE6FFBF247E5D",
"7345E07732B71CB158BBF64CCA5C5B96",
"6E128F296D24705A1924FD9B70C4ED04",
"95A789776F036783FBD330947083F54F",
"360DEC2533EA4AA2E3E54FD3DE2906EB",
"E68EFD7FECF4D601EA22727BD764965B",
"9065C64A8BFF44AC33EDBB611CF83D7B",
"8F33C8DF2A7A51CE8090E8F123BC3723",
"807F391FFBA8291BA625623210F99018",
"5E8B3F3A701522CE5CAA761C929D6292",
"3BA404DC38735A78289E3809E8364835",
"D23BEDBAD229F8305DC425B6B759DCC9",
"44880F21CF5913040AE376AEE2A10AD8",
"9BC98E29D057C0E828C3B5CCE69256C1",
"B293CC7A975DA141A68279368057CC41",
"8D60FB87ACD91385B313BE5F1D7BD30F",
"2C8E56132D70291B303C48FDF75543CD",
"D1F80035B826791F6CE4E59B7DB1BB0D",
"42CE6224FC36469339A133DD08173BD4",
"61817155EA41BCBA2AF7F06AE7CBF585",
"D1923A9866068D2EF5FB77D57C3315B6",
"B37CBDB5D719F49691CA968EF2E84140",
"EC974E653A055D7F8F22171030F68E1D",
"DDE5D3B9AAD9C32213BB3675A822499C",
"D3B6E9216EA1AE57EB1C628A3C38AB78",
"82C99ECC69472B7E96324B042AE8B87A",
"97144DC5338C43600F84439C0AA0D147",
"400AC4A0BBADA1DB2121EB144C7E5209",
"EFD9D550EB419ED278F4885A490AB54C",
"2AB7816E149B7C0404C88A8857793670",
"5B591DFF9E8DEE15BAD24C025DBCA481",
"0C06633E30721C3749F49AD8CBF2B754",
"96D6D31A41B5123B2035FD91A921D4CA",
"E7F6C34D86668BC2805CA7793C5E86AD",
"F46DFF5FF500D6879C4D3E45CF0CF0F3",
"60D842D9C61DA7495C116197B7CECBBE",
"D45B24EDB673353EBDF248B8FA06B67A",
"119EAEBCC165D0BD02C0D35DC82EF992",
"E673143680414ADA301D0ED34626B9FE",
"6B6CFE160A6263631B292F879EEFF926"
}
};
private static int[] KEY_SIZES = {
16, 24, 32
};
/**
* Constructs an AES Key according to the specified key size and
* round number.
* @param len key size in bytes, i.e. 16, 24, or 32
* @param rounds round number starting from 0, i.e. valid from 0 to len-1.
*/
private static SecretKey constructAESKey(int len, int rounds)
throws IllegalArgumentException {
if ((len != 16) && (len != 24) && (len != 32)) {
throw new IllegalArgumentException("Wrong Key Length: " + len);
}
byte[] rawKeyValue = constructKeyValue(len, rounds);
SecretKeySpec key = new SecretKeySpec(rawKeyValue, "AES");
return key;
}
private static byte[] constructKeyValue(int keysize, int rounds) {
byte[] tempKeyValue = new byte[keysize];
Arrays.fill(tempKeyValue, (byte)0);
int whichByte = rounds/8;
int whichDigit = rounds % 8;
if ((whichByte >= keysize) || (whichDigit < 0) ||
(whichDigit > 8)) {
throw new IllegalArgumentException("Invalid keysize/rounds " +
"combination :" + keysize +
"/" + rounds);
}
switch (whichDigit) {
case 0:
tempKeyValue[whichByte] = (byte)0x80;
break;
case 1:
tempKeyValue[whichByte] = (byte)0x40;
break;
case 2:
tempKeyValue[whichByte] = (byte)0x20;
break;
case 3:
tempKeyValue[whichByte] = (byte)0x10;
break;
case 4:
tempKeyValue[whichByte] = (byte)0x08;
break;
case 5:
tempKeyValue[whichByte] = (byte)0x04;
break;
case 6:
tempKeyValue[whichByte] = (byte)0x02;
break;
case 7:
tempKeyValue[whichByte] = (byte)0x01;
break;
}
return tempKeyValue;
}
private static byte[] constructByteArray(String s) {
int len = s.length()/2;
byte[] tempValue = new byte[len];
for (int i = 0; i < len; i++) {
tempValue[i] = Integer.valueOf(s.substring(2*i, 2*i+2),
16).byteValue();
}
return tempValue;
}
public boolean execute() throws Exception {
String transformation = ALGO+"/"+MODE+"/"+PADDING;
Cipher c = Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
for (int i=0; i<KEY_SIZES.length; i++) {
if (KEY_SIZES[i]*8 >
Cipher.getMaxAllowedKeyLength(transformation)) {
// skip if this key length is larger than what's
// configured in the jce jurisdiction policy files
continue;
}
int rounds = KEY_SIZES[i] * 8;
byte[] plainText = PT;
byte[] cipherText = null;
try {
for (int j=0; j < rounds; j++) {
SecretKey aesKey = constructAESKey(KEY_SIZES[i], j);
c.init(Cipher.ENCRYPT_MODE, aesKey);
cipherText = c.doFinal(plainText);
byte[] answer = constructByteArray(CTS[i][j]);
if (!Arrays.equals(cipherText, answer)) {
throw new Exception((i+1) + "th known answer test failed for encryption");
}
c.init(Cipher.DECRYPT_MODE, aesKey);
byte[] restored = c.doFinal(cipherText);
if (!Arrays.equals(plainText, restored)) {
throw new Exception((i+1) + "th known answer test failed for decryption");
}
}
System.out.println("Finished KAT for " + KEY_SIZES[i] + "-byte key");
} catch (SecurityException se) {
TestUtil.handleSE(se);
}
}
// passed all tests...hooray!
return true;
}
public static void main (String[] args) throws Exception {
TestKATForECB_VK test = new TestKATForECB_VK();
String testName = test.getClass().getName() + "[" + ALGO +
"/" + MODE + "/" + PADDING + "]";
if (test.execute()) {
System.out.println(testName + ": Passed!");
}
}
}

View file

@ -0,0 +1,565 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4635086
* @library ../UTIL
* @build TestUtil
* @run main TestKATForECB_VT
* @summary Known Answer Test for AES cipher with ECB mode
* @author Valerie Peng
*/
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.math.*;
import java.util.*;
public class TestKATForECB_VT
{
private static final String ALGO = "AES";
private static final String MODE = "ECB";
private static final String PADDING = "NoPadding";
private static String[][] CTS = {
// Cipher Texts for 128-bit key
{
"3AD78E726C1EC02B7EBFE92B23D9EC34",
"45BC707D29E8204D88DFBA2F0B0CAD9B",
"161556838018F52805CDBD6202002E3F",
"F5569B3AB6A6D11EFDE1BF0A64C6854A",
"64E82B50E501FBD7DD4116921159B83E",
"BAAC12FB613A7DE11450375C74034041",
"BCF176A7EAAD8085EBACEA362462A281",
"47711816E91D6FF059BBBF2BF58E0FD3",
"B970DFBE40698AF1638FE38BD3DF3B2F",
"F95B59A44F391E14CF20B74BDC32FCFF",
"720F74AE04A2A435B9A7256E49378F5B",
"2A0445F61D36BFA7E277070730CF76DA",
"8D0536B997AEFEC1D94011BAB6699A03",
"674F002E19F6ED47EFF319E51FAD4498",
"292C02C5CB9163C80AC0F6CF1DD8E92D",
"FA321CF18EF5FE727DD82A5C1E945141",
"A5A7AFE1034C39CCCEBE3C584BC0BE05",
"4FF5A52E697E77D081205DBDB21CEA39",
"209E88DC94C9003000CE0769AF7B7166",
"5DEE41AF864CB4B650E5F51551824D38",
"A79A63FA7E4503AE6D6E09F5F9053030",
"A48316749FAE7FAC7002031A6AFD8BA7",
"D6EEE8A7357A0E1D64262CA9C337AC42",
"B013CA8A62A858053E9FB667ED39829E",
"DF6EA9E4538A45A52D5C1A43C88F4B55",
"7D03BA451371591D3FD5547D9165C73B",
"0E0426281A6277E186499D365D5F49FF",
"DBC02169DD2059E6CC4C57C1FEDF5AB4",
"826590E05D167DA6F00DCC75E22788EB",
"34A73F21A04421D9786335FAAB49423A",
"ED347D0E0128EE1A7392A1D36AB78AA9",
"EE944B2FE6E9FC888042608DA9615F75",
"9E7C85A909EF7218BA7947CFB4718F46",
"811AE07A0B2B1F816587FA73699AE77D",
"68466FBF43C2FE13D4B18F7EC5EA745F",
"D20B015C7191B219780956E6101F9354",
"5939D5C1BBF54EE1B3E326D757BDDE25",
"B1FDAFE9A0240E8FFEA19CE94B5105D3",
"D62962ECE02CDD68C06BDFEFB2F9495B",
"B3BB2DE6F3C26587BA8BAC4F7AD9499A",
"E0B1072D6D9FF703D6FBEF77852B0A6B",
"D8DD51C907F478DE0228E83E61FD1758",
"A42DFFE6E7C1671C06A25236FDD10017",
"25ACF141550BFAB9EF451B6C6A5B2163",
"4DA7FCA3949B16E821DBC84F19581018",
"7D49B6347CBCC8919C7FA96A37A7A215",
"900024B29A08C6721B95BA3B753DDB4D",
"6D2182FB283B6934D90BA7848CAB5E66",
"F73EF01B448D23A4D90DE8B2F9666E7A",
"4AD9CDA2418643E9A3D926AF5E6B0412",
"7CAEC8E7E5953997D545B033201C8C5B",
"3C43CA1F6B6864503E27B48D88230CF5",
"44F779B93108FE9FEEC880D79BA74488",
"9E50E8D9CFD3A682A78E527C9072A1CF",
"68D000CBC838BBE3C505D6F814C01F28",
"2CB2A9FEC1ACD1D9B0FA05205E304F57",
"01EB2806606E46444520A5CC6180CD4B",
"DAA9B25168CC702326F217F1A0C0B162",
"3E07E648975D9578D03555B1755807ED",
"0B45F52E802C8B8DE09579425B80B711",
"659595DA0B68F6DF0DD6CA77202986E1",
"05FF42873893536E58C8FA98A45C73C4",
"B5B03421DE8BBFFC4EADEC767339A9BD",
"788BCD111ECF73D4E78D2E21BEF55460",
"909CD9EC6790359F982DC6F2393D5315",
"332950F361535FF24EFAC8C76293F12C",
"A68CCD4E330FFDA9D576DA436DB53D75",
"27C8A1CCFDB0B015D1ED5B3E77143791",
"D76A4B95887A77DF610DD3E1D3B20325",
"C068AB0DE71C66DAE83C361EF4B2D989",
"C2120BCD49EDA9A288B3B4BE79AC8158",
"0C546F62BF2773CD0F564FCECA7BA688",
"18F3462BEDE4920213CCB66DAB1640AA",
"FE42F245EDD0E24B216AEBD8B392D690",
"3D3EEBC8D3D1558A194C2D00C337FF2B",
"29AAEDF043E785DB42836F79BE6CBA28",
"215F90C6744E2944358E78619159A611",
"8606B1AA9E1D548E5442B06551E2C6DC",
"987BB4B8740EC0EDE7FEA97DF033B5B1",
"C0A3500DA5B0AE07D2F450930BEEDF1B",
"525FDF8312FE8F32C781481A8DAAAE37",
"BFD2C56AE5FB9C9DE33A6944572A6487",
"7975A57A425CDF5AA1FA929101F650B0",
"BF174BC49609A8709B2CD8366DAA79FE",
"06C50C43222F56C874B1704E9F44BF7D",
"0CEC48CD34043EA29CA3B8ED5278721E",
"9548EA34A1560197B304D0ACB8A1698D",
"22F9E9B1BD73B6B5B7D3062C986272F3",
"FEE8E934BD0873295059002230E298D4",
"1B08E2E3EB820D139CB4ABBDBE81D00D",
"0021177681E4D90CEAF69DCED0145125",
"4A8E314452CA8A8A3619FC54BC423643",
"65047474F7222C94C6965425FF1BFD0A",
"E123F551A9C4A8489622B16F961A9AA4",
"EF05530948B80915028BB2B6FE429380",
"72535B7FE0F0F777CEDCD55CD77E2DDF",
"3423D8EFC31FA2F4C365C77D8F3B5C63",
"DE0E51C264663F3C5DBC59580A98D8E4",
"B2D9391166680947AB09264156719679",
"10DB79F23B06D263835C424AF749ADB7",
"DDF72D27E6B01EC107EA3E005B59563B",
"8266B57485A5954A4236751DE07F6694",
"669A501E1F1ADE6E5523DE01D6DBC987",
"C20C48F2989725D461D1DB589DC0896E",
"DE35158E7810ED1191825D2AA98FA97D",
"4FE294F2C0F34D0671B693A237EBDDC8",
"087AE74B10CCBFDF6739FEB9559C01A4",
"5DC278970B7DEF77A5536C77AB59C207",
"7607F078C77085184EAA9B060C1FBFFF",
"9DB841531BCBE7998DAD19993FB3CC00",
"D6A089B654854A94560BAE13298835B8",
"E1E223C4CF90CC5D195B370D65114622",
"1CBED73C50D053BDAD372CEEE54836A1",
"D309E69376D257ADF2BFDA152B26555F",
"740F7649117F0DEE6EAA7789A9994C36",
"76AE64417C297184D668C5FD908B3CE5",
"6095FEA4AA8035591F1787A819C48787",
"D1FF4E7ACD1C79967FEBAB0F7465D450",
"5F5AD3C42B9489557BB63BF49ECF5F8A",
"FB56CC09B680B1D07C5A52149E29F07C",
"FF49B8DF4A97CBE03833E66197620DAD",
"5E070ADE533D2E090ED0F5BE13BC0983",
"3AB4FB1D2B7BA376590A2C241D1F508D",
"58B2431BC0BEDE02550F40238969EC78",
"0253786E126504F0DAB90C48A30321DE",
"200211214E7394DA2089B6ACD093ABE0",
"0388DACE60B6A392F328C2B971B2FE78",
"58E2FCCEFA7E3061367F1D57A4E7455A"
},
// Cipher Texts for 192-bit key
{
"6CD02513E8D4DC986B4AFE087A60BD0C",
"423D2772A0CA56DAABB48D2129062987",
"1021F2A8DA70EB2219DC16804445FF98",
"C636E35B402577F96974D8804295EBB8",
"1566D2E57E8393C19E29F892EA28A9A7",
"883C878FED70B36CC09D040F9619DD19",
"06734593A974965790E715594FC34AA9",
"F19B389948D9A45534E5BD36C984134A",
"D8410DFC14FA6D175EC968EA8CAC514C",
"7E6C6EBB4029A177CF7B2FDD9AC6BB7A",
"4B51DD4850DC0A6C3A46D924003D2C27",
"2E510A9D917B15BE32A192B12A668F23",
"88F6F79962B0FB77FEA8E7C632D3108E",
"A3A35AB1D88DAF07B52794A0F065383A",
"DC6CC878433E2B3BB193049A4ECBFC53",
"EFCD3763EB7B1A415938248A9A5B4FD5",
"AB7E9FB9A66DBE5BB44854F07D9015EE",
"8B8E9D3365F8F6743ECF7E33E99255A4",
"54D37B4F176FF3D8F6AFC866066D8572",
"E83310889480FBF3C00342E3126D0D02",
"D321AB2511F92F098174AA2DE6E85DA2",
"D8E3F40B1112D5149D58C481DFA9983F",
"2454C4E0806639DDF19854D6C68054AD",
"A5506D410F7CA32F3955DD79D9D09418",
"7908EE40677699568A7DC1AA317C7E4E",
"B4B7B29DD43B2F5CF765E25192273982",
"92AFE9668159BEFFE2A86F8503260164",
"5C36A232FBA6D187A84657AD4028B18F",
"A2E994DFAB3A798DF8F54F6DA87E58E2",
"6CDAB10A72ADF77D71D0765BAAE95631",
"9FE3C801BCAAF7BB800F2E6BF3278E21",
"B459D90D9A6C392E5493BC91CF5A0863",
"0518A9FA5007F6787E0FB4E5AC27D758",
"BED9795415D28599700ED7952384A963",
"F0140421173D60251EF6CAB0229B1B50",
"460EB4652B3F6779EA28CB11B37529ED",
"C4283D351C960A6AC13CD19CCF03AE38",
"6815A10047B2C834A798EBDCC6786C75",
"99BA19F0CDD5990D0386B32CE56C9C4C",
"DE76F62C61E07915162DA13E79679DEC",
"DD0325D6854803D06D1D2277D5FB8D67",
"580B71A41DE37D6FAC83CCB0B3BB1C97",
"E9B1AB470A1B02EF0FF5E6754A092C96",
"8590620F5AF5993B7410282F4126BC1F",
"8D4914D2F1B22B2E268E66E532D29D7C",
"FD826CE48E62C5E30867044B86BA4B56",
"100E7B831C9F35FA1271F5F1316C6FCF",
"0A2DD0C17F68B996AA96C007003D0B31",
"C95F68C57E06B0A2E1F623C83C5D80BF",
"571CAFC92C7C8A5EC54C0741E186905C",
"22514353E95312C112255E1EED0B2DF6",
"791A8BF462BD17580BD9152C6D11C6C5",
"5882A0178D548F84A165DB809C60DC28",
"3CE4A90EED4458CA6039E42DDADB71C3",
"D3CBAB261207A16BE2751E77044FD7C9",
"24E32B698A7B32217093628B01F424AB",
"9F6AFC0AF27CF565110C77E3C24F4F5B",
"E088AA5CDA20EF267BB039B00C72C45B",
"5CF1018B7E0BA1775601C2E279900360",
"3B1A7388B89FB9416AD8753CF5AF35D2",
"137FA4ED00AFCD9F5D8BC0D14BD5837A",
"806F5C9B663559BB56F234881E4A3E60",
"8069A449152292DF2DE8642992C632B6",
"37C6CF2A1ABD1B1F1922B46C7B4A280D",
"7A2835260E5A0AA2B5DC301800EC8438",
"EE81FAF2F9058213FFCACF281CB8509E",
"57F22D93C37129BA331FDBA38E005A1E",
"EC798782E87B7D9F780CC3C3A46519B5",
"43EA28497F5D40E3A4744FA2EDAA42DE",
"91F004E7DEBF41B3414DD8C5C317372C",
"C249EAE54E7B4DF43B938C1B4CC28314",
"32C289D7EEFB99D2F17AD7B7D45FE1EC",
"A675FB2E8DDBF810CEF01CF2B728CD2B",
"A418AAAB6E6921CC731AA8A349386080",
"2E2B0F44863E67D9B0215C4ABD60417F",
"F0AF7CB19E911D481F6426DAEFDD2240",
"CB1304DAAA2DF6878F56AC2E0F887E04",
"B1B70A7E6A0CD1916D9B78BEA19084AE",
"0CDE9F9BE646A5FCE3436B794A9CFC65",
"68C7946D476A0A36674B36AFD7E5DF33",
"48770159A07DD8DFFF06C80105F8D57C",
"665E62801B3260E3C45BD3BE34DFDEBE",
"4159C1F686BFBE5B0E50BDB0DA532B69",
"6333100A5A4AD917DC2D4E78A04869A3",
"866A4519AB1D199F25886B89D0539ACC",
"EC0CFD37E4CBC7E8BE385283F7AEA75A",
"CA2F383AACCA0810AA13F3E710621422",
"1D0EEF6870444F950937831EC0A55D98",
"37839B35ED6801E7670496D479A95017",
"02317C8C7098C4F94AB867AC7A49DD8D",
"FFB4CB4E3F7F8BF3367EBD43236518B4",
"36BEDEF1E4AA3E4A40A305741713FCBF",
"B2DFE3C4870269C1E3FEEC39161540D9",
"147EF2518AD45DA0026056ECBF6A3DFA",
"027A75E4DE635790E47ACE90D7928804",
"C4CF3CCB59BF87D0AFBD629F48CFBB7B",
"35165C93F564C97E1C32EF97E8151A87",
"449DE37F7D5A1BBD628ABBE7E061701D",
"B1D45EAF218F1799B149BAD677FE129F",
"BE08AC6DB6BD0583AA9D2ABC71C73DCD",
"BCC835BD3DF1A79E4C7C145B899A5C25",
"3D311EA611FF5AF371301C58A8E9912D",
"A5A1BEA594ACC7CA80F09EA5ADDB5C71",
"0F09492429FE7222D6CD8190D9F2FFBF",
"816D2220A16B8AAEE71364FD43636C6F",
"D7E8702408419ED73191B107EAF75A0B",
"9B170EFB1E235B433C78E276BEA082F0",
"03BBECC5598AE974430F29395522F096",
"DB53517766C0E8CF42059607CBA89380",
"2E2AF4B7931F0AEFFAC5471148A5BB97",
"C872C0408266403B984F635FF5683DE4",
"15DCF750B0E3A68AD1F4EFD07E8967B4",
"B41092048E9E6A749F6FD8CE515A23A3",
"4DA9267D62507994312BD5C99ADDE730",
"9E2FCA6D1D626E9C6A924EBF7DBF618A",
"E092E8D7EF2C2465AEFB2493C3063590",
"1C0E58DA37D1068378A88DBE2EDE4E10",
"19063F854232B8509A6A3A6D46809959",
"447FB09E54EFA285F7530F25C4EA0022",
"F6ABE86321BE40E1FBFDAFED37CC1D9B",
"4E8506CD006666341D6CF51F98B41F35",
"53995DE0009CA18BECAFB8307C54C14C",
"2006BF99F4C58B6CC2627856593FAEEA",
"2DA697D2737CB30B744A4644FA1CBC6E",
"47A22ACDB60C3A986A8F76ECD0EA3433",
"FDAA17C2CDE20268FE36E164EA532151",
"98E7247C07F0FE411C267E4384B0F600",
"CD33B28AC773F74BA00ED1F312572435"
},
// Cipher Texts for 256-bit key
{
"DDC6BF790C15760D8D9AEB6F9A75FD4E",
"C7098C217C334D0C9BDF37EA13B0822C",
"60F0FB0D4C56A8D4EEFEC5264204042D",
"73376FBBF654D0686E0E84001477106B",
"2F443B52BA5F0C6EA0602C7C4FD259B6",
"75D11B0E3A68C4223D88DBF017977DD7",
"779B38D15BFFB63D8D609D551A5CC98E",
"5275F3D86B4FB8684593133EBFA53CD3",
"1CEF2074B336CEC62F12DEA2F6AB1481",
"1AEF5ABBAD9D7160874578DCD8BAE172",
"46C525DB17E72F26BF03216846B6F609",
"E24411F941BBE08788781E3EC52CBAA4",
"83A3DEDD1DD27018F6A6477E40527581",
"B68F8A2CDBAB0C923C67FC8F0F1087DE",
"649944A70C32BF87A7409E7AE128FDE8",
"2846526D67387539C89314DE9E0C2D02",
"A9A0B8402E53C70DD1688054BA58DDFD",
"4A72E6E1B79C83AC4BE3EBA5699EED48",
"B0E36B867BA4FF2B77D0614B0E364E4C",
"49B57DE141F6418E3090F24DDD4014B6",
"A6C0D5B9797258E1987AC5F6CD20146D",
"426CF4BDCAA369175965D26E7C71EEA2",
"E27F484CE54BC99BC1A52BDA3B518A26",
"D16D186284C7E6EE64B8104E0EF20BA5",
"6431F8538AD54E1E044A9F71F8EF556B",
"ECD57CEB451D27EB96C55B2042257E8E",
"4F0F188DC911B1954AFBC734C9F68872",
"B54DEF0337626B65614E81EDFDE620F3",
"6655D8074CAE0B90B0D3A3FE72D4D9DB",
"C6B74B6B9EB4FC0C9A237DB1B616D09A",
"D7B5D076EA56EC2B20791D7AD51CCF8F",
"FE160C224BF003CE3BDDC90CB52ED22C",
"5E00DA9BA94B5EC0D258D8A8002E0F6A",
"09AC6DCFF4DACFF1651E2BA212A292A3",
"B283617E318D99AF83A05D9810BA89F7",
"0B5F70CCB40B0EF2538AE9B4A9770B35",
"43282BF180248FB517839B37F4DDAAE4",
"DDBD534C8B2E6D30A268F88C55AD765B",
"A41A164E50EC2D9F175E752B755E0B5C",
"37BFF99FF2F7AA97779E4ADF6F13FB10",
"9BA4F7BD298152903A683C4CEC669216",
"5FB750C7CE10DE7B4504248914D0DA06",
"3E748BFA108E086F51D56EC74A9E0FB9",
"31D4E56B99F5B73C1B8437DF332AFB98",
"9DC6717B84FC55D266E7B1D9B5C52A5F",
"8EF8BA007F23C0A50FC120E07041BCCD",
"C58F38E1839FC1918A12B8C9E88C66B6",
"B695D72A3FCF508C4050E12E40061C2D",
"5D2736AD478A50583BC8C11BEFF16D7A",
"DF0EACA8F17847AD41F9578F14C7B56B",
"E5AA14AD48AD0A3C47CC35D5F8020E51",
"11BE6C8F58EBD8CEF1A53F591A68E8CE",
"ECFE7BAFCBF42C1FEE015488770B3053",
"E552649F8D8EC4A1E1CD6DF50B6E6777",
"521C0629DE93B9119CDB1DDC5809DDEA",
"CB38A62A0BAB1784156BA038CBA99BF6",
"76CCEE8AAACD394DE1EEF3DDA10CB54B",
"6AFF910FA1D5673140E2DB59B8416049",
"064A12C0EF73FB386801BF4F35F3120D",
"2240E374929D5B1BB8FF0FFDDDF640EC",
"D4BA15C904C7692185DE85C02052E180",
"1714A315AB0166728A44CD91D4AE9018",
"6C970BDD9F0E222722EA31A1D12DD0AD",
"F5956EDF02BD36A401BBB6CE77C3D3FB",
"0CA11F122CCD7C259DC597EED3DF9BC4",
"50109AB4912AD2560B206F331B62EB6C",
"DBE7C91A4175614889A2D4BEFD64845E",
"0D3322853A571A6B46B79C0228E0DD25",
"96E4EE0BB9A11C6FB8522F285BADDEB6",
"96705C52D2CFCE82E630C93477C79C49",
"C50130AED6A126149D71F3888C83C232",
"4816EFE3DEB380566EBA0C17BF582090",
"0390857B4C8C98E4CF7A2B6F3394C507",
"422E73A02025EBE8B8B5D6E0FA24FCB2",
"3271AA7F4BF1D7C38050A43076D4FF76",
"D2074946F0D37B8975607BFC2E70234C",
"1A509194C1270AB92E5A42D3A9F8D98B",
"512438946360CCC4A5C6D73F6EED7130",
"98CFCDEC46EBEA1A286B3004F2746A0D",
"A1CF369949677A3AF3D58E3EABF2741B",
"D84C2E1A0E4A52166FA8FF6889D1E5E2",
"4AD91CCEEF60119B5078FD162D2735DE",
"2860793D818E97AAFF1D339D7702438D",
"6F9068BE73364AE250D89D78A6C9CE6F",
"024FC3FEF4883FEB1A8DD005305FECCE",
"08A61FE0816D75EA15EB3C9FB9CCDED6",
"449C86DFA13F260175CE39797686FFA4",
"4FFFFC29A59858E1133F2BFB1A8A4817",
"19425D1F6480B25096561295697DC2B7",
"31974727ECDD2C77C3A428FC3A8CB3FC",
"A57CD704B3C95E744D08DF443458F2F5",
"486D8C193DB1ED73ACB17990442FC40B",
"5E4DBF4E83AB3BC055B9FCC7A6B3A763",
"ACF2E0A693FBBCBA4D41B861E0D89E37",
"32A7CB2AE066A51D2B78FC4B4CFCB608",
"677D494DBB73CAF55C1990158DA12F14",
"082A0D2367512ADF0D75A151BFBE0A17",
"5E5BB7337923C482CE8CBA249E6A8C7D",
"D3001BA7C7026EE3E5003179530AFCFC",
"46EC44F8931E629FE8FD8961312EDDE1",
"C5F8ECD79C7B30E81D17E32079969310",
"5B8AD6919E24CAEBCC55401AEE0C9802",
"C2302B7E701B5CC7F8B29E3516DBBFA6",
"A1D04D6A76F9F7A94D49FAA64A87F244",
"7FB6F92D35B5CB6C631600EDB9E860BA",
"B2EF7078BCFACE07AEEC3F9B48830EB3",
"F475A7493D24C7036E53390374C378B3",
"B36802AC987377A37BD8EADC97C57D60",
"ADDCD3D19689C4DDC738CE5F69DC9505",
"0DAF8CA22884915403C0F0BB1F4BD74F",
"4AF36BAE2660503B3248E4685059FD05",
"7D5631814DD8E917D97A0D514C743971",
"BC3352500FC0CBB9DB5B5F6B491C1BE8",
"6A4A30BA87E87AF65C90AEB7AFEDC76B",
"77E6125897668AC8E73E8C79A6FF8336",
"3FA9D39104EBB323C7AAAA248960DD1E",
"FAD75AD76AB10ADC49036B250E229D39",
"2FACAA5FE35B228A16AC74088D702EC4",
"88B6CBCFDFEF8AD91720A1BB69A1F33E",
"C7E9D250998632D444356242EF04058D",
"B14DAD8D3D9153F46C0D3A1AD63C7A05",
"60ABA678A506608D0845966D29B5F790",
"482DC43F2388EF25D24144E144BD834E",
"1490A05A7CEE43BDE98B56E309DC0126",
"ABFA77CD6E85DA245FB0BDC5E52CFC29",
"DD4AB1284D4AE17B41E85924470C36F7",
"CEA7403D4D606B6E074EC5D3BAF39D18",
"530F8AFBC74536B9A963B4F1C4CB738B"
}
};
private static int[] KEY_SIZES = {
16, 24, 32
};
/**
* Constructs an AES Key according to the specified key size.
* @param len key size in bytes, i.e. 16, 24, or 32
*/
private static SecretKey constructAESKey(int len)
throws IllegalArgumentException {
if ((len != 16) && (len != 24) && (len != 32)) {
throw new IllegalArgumentException("Wrong Key Length: " + len);
}
byte[] keyval = new byte[len];
return new SecretKeySpec(keyval, "AES");
}
/**
* Constructs plain text byte array according to the specified round
* number.
* @param rounds round number starting from 0, i.e. valid from 0
* to 127.
*/
private static byte[] constructPT(int rounds) {
byte[] tempValue = new byte[16];
Arrays.fill(tempValue, (byte)0);
int whichByte = rounds/8;
int whichDigit = rounds % 8;
if ((whichByte >= 16) || (whichDigit < 0) ||
(whichDigit > 8)) {
throw new IllegalArgumentException("Invalid rounds: " +
rounds);
}
switch (whichDigit) {
case 0:
tempValue[whichByte] = (byte)0x80;
break;
case 1:
tempValue[whichByte] = (byte)0x40;
break;
case 2:
tempValue[whichByte] = (byte)0x20;
break;
case 3:
tempValue[whichByte] = (byte)0x10;
break;
case 4:
tempValue[whichByte] = (byte)0x08;
break;
case 5:
tempValue[whichByte] = (byte)0x04;
break;
case 6:
tempValue[whichByte] = (byte)0x02;
break;
case 7:
tempValue[whichByte] = (byte)0x01;
break;
}
return tempValue;
}
private static byte[] constructByteArray(String s) {
int len = s.length()/2;
byte[] tempValue = new byte[len];
for (int i = 0; i < len; i++) {
tempValue[i] = Integer.valueOf(s.substring(2*i, 2*i+2),
16).byteValue();
}
return tempValue;
}
public boolean execute() throws Exception {
String transformation = ALGO+"/"+MODE+"/"+PADDING;
Cipher c = Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
for (int i=0; i<KEY_SIZES.length; i++) {
if (KEY_SIZES[i]*8 >
Cipher.getMaxAllowedKeyLength(transformation)) {
// skip if this key length is larger than what's
// configured in the jce jurisdiction policy files
continue;
}
SecretKey aesKey = constructAESKey(KEY_SIZES[i]);
byte[] plainText = null;
byte[] cipherText = null;
try {
for (int j=0; j < 128; j++) {
plainText = constructPT(j);
c.init(Cipher.ENCRYPT_MODE, aesKey);
cipherText = c.doFinal(plainText);
byte[] answer = constructByteArray(CTS[i][j]);
if (!Arrays.equals(cipherText, answer)) {
throw new Exception((i+1) +
"th known answer test failed for encryption");
}
c.init(Cipher.DECRYPT_MODE, aesKey);
byte[] restored = c.doFinal(cipherText);
if (!Arrays.equals(plainText, restored)) {
throw new Exception((i+1) +
"th known answer test failed for decryption");
}
}
System.out.println(
"Finished KAT for " + KEY_SIZES[i] + "-byte key");
} catch (SecurityException se) {
TestUtil.handleSE(se);
}
}
// passed all tests...hooray!
return true;
}
public static void main (String[] args) throws Exception {
TestKATForECB_VT test = new TestKATForECB_VT();
String testName = test.getClass().getName() + "[" + ALGO +
"/" + MODE + "/" + PADDING + "]";
if (test.execute()) {
System.out.println(testName + ": Passed!");
}
}
}

View file

@ -0,0 +1,418 @@
/*
* Copyright (c) 2013, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 6996769
* @library ../UTIL
* @build TestUtil
* @run main TestKATForGCM
* @summary Known Answer Test for AES cipher with GCM mode support in
* SunJCE provider.
* @author Valerie Peng
*/
import java.nio.ByteBuffer;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.math.*;
import java.util.*;
public class TestKATForGCM {
// Utility methods
private static byte[] HexToBytes(String hexVal) {
if (hexVal == null) return new byte[0];
byte[] result = new byte[hexVal.length()/2];
for (int i = 0; i < result.length; i++) {
// 2 characters at a time
String byteVal = hexVal.substring(2*i, 2*i +2);
result[i] = Integer.valueOf(byteVal, 16).byteValue();
}
return result;
}
private static class TestVector {
int id;
SecretKey key;
byte[] plainText;
byte[] aad;
byte[] cipherText;
byte[] tag;
GCMParameterSpec spec;
String info;
TestVector(int id, String key, String iv, String pt, String aad,
String ct, String tag) {
this.id = id;
this.key = new SecretKeySpec(HexToBytes(key), "AES");
this.plainText = HexToBytes(pt);
this.aad = HexToBytes(aad);
this.cipherText = HexToBytes(ct);
this.tag = HexToBytes(tag);
this.spec = new GCMParameterSpec(this.tag.length * 8, HexToBytes(iv));
this.info = "id = " + id + ", key=" + key + ", iv=" + iv + ", pt=" + pt +
",aad=" + aad + ", ct=" + ct + ", tag=" + tag;
}
TestVector() {};
TestVector duplicate() {
TestVector t = new TestVector();
t.id = id;
t.key = key;
t.plainText = plainText;
t.cipherText = cipherText;
t.aad = aad;
t.tag = tag;
t.spec = spec;
t.info = info;
return t;
}
public String toString() {
return info;
}
}
static boolean testFailed = false;
// These test vectors are found off NIST's CAVP page
// http://csrc.nist.gov/groups/STM/cavp/index.html
// inside the link named "GCM Test Vectors", i.e.
// http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
// CAVS 14.0, set of test vectors w/ count = 0, keysize = 128
private static TestVector[] testValues = {
// 96-bit iv w/ 128/120/112/104/96-bit tags
// no plain text, no aad
new TestVector(1, "11754cd72aec309bf52f7687212e8957",
"3c819d9a9bed087615030b65",
null, null, null,
"250327c674aaf477aef2675748cf6971"),
new TestVector(2, "272f16edb81a7abbea887357a58c1917",
"794ec588176c703d3d2a7a07",
null, null, null,
"b6e6f197168f5049aeda32dafbdaeb"),
new TestVector(3, "81b6844aab6a568c4556a2eb7eae752f",
"ce600f59618315a6829bef4d",
null, null, null,
"89b43e9dbc1b4f597dbbc7655bb5"),
new TestVector(4, "cde2f9a9b1a004165ef9dc981f18651b",
"29512c29566c7322e1e33e8e",
null, null, null,
"2e58ce7dabd107c82759c66a75"),
new TestVector(5, "b01e45cc3088aaba9fa43d81d481823f",
"5a2c4a66468713456a4bd5e1",
null, null, null,
"014280f944f53c681164b2ff"),
// 96-bit iv w/ 128/120/112/104/96-bit tags
// no plain text, 16-byte aad
new TestVector(6, "77be63708971c4e240d1cb79e8d77feb",
"e0e00f19fed7ba0136a797f3",
null,
"7a43ec1d9c0a5a78a0b16533a6213cab",
null,
"209fcc8d3675ed938e9c7166709dd946"),
new TestVector(7, "da0b615656135194ba6d3c851099bc48",
"d39d4b4d3cc927885090e6c3",
null,
"e7e5e6f8dac913036cb2ff29e8625e0e",
null,
"ab967711a5770461724460b07237e2"),
new TestVector(8, "7e0986937a88eef894235aba4a2f43b2",
"92c4a631695907166b422d60",
null,
"85c185f8518f9f2cd597a8f9208fc76b",
null,
"3bb916b728df94fe9d1916736be1"),
new TestVector(9, "c3db570d7f0c21e86b028f11465d1dc9",
"f86970f58ceef89fc7cb679e",
null,
"c095240708c0f57c288d86090ae34ee1",
null,
"e043c52160d652e82c7262fcf4"),
new TestVector(10, "bea48ae4980d27f357611014d4486625",
"32bddb5c3aa998a08556454c",
null,
"8a50b0b8c7654bced884f7f3afda2ead",
null,
"8e0f6d8bf05ffebe6f500eb1"),
// 96-bit iv w/ 128/120/112/104/96-bit tags
// no plain text, 20-byte aad
new TestVector(11, "2fb45e5b8f993a2bfebc4b15b533e0b4",
"5b05755f984d2b90f94b8027",
null,
"e85491b2202caf1d7dce03b97e09331c32473941",
null,
"c75b7832b2a2d9bd827412b6ef5769db"),
new TestVector(12, "9bf406339fcef9675bbcf156aa1a0661",
"8be4a9543d40f542abacac95",
null,
"7167cbf56971793186333a6685bbd58d47d379b3",
null,
"5e7968d7bbd5ba58cfcc750e2ef8f1"),
new TestVector(13, "a2e962fff70fd0f4d63be728b80556fc",
"1fa7103483de43d09bc23db4",
null,
"2a58edf1d53f46e4e7ee5e77ee7aeb60fc360658",
null,
"fa37f2dbbefab1451eae1d0d74ca"),
new TestVector(14, "6bf4fdce82926dcdfc52616ed5f23695",
"cc0f5899a10615567e1193ed",
null,
"3340655592374c1da2f05aac3ee111014986107f",
null,
"8ad3385cce3b5e7c985908192c"),
new TestVector(15, "4df7a13e43c3d7b66b1a72fac5ba398e",
"97179a3a2d417908dcf0fb28",
null,
"cbb7fc0010c255661e23b07dbd804b1e06ae70ac",
null,
"37791edae6c137ea946cfb40"),
// 96-bit iv w/ 128-bit tags, 13/16/32/51-byte plain text, no aad
new TestVector(16, "fe9bb47deb3a61e423c2231841cfd1fb",
"4d328eb776f500a2f7fb47aa",
"f1cc3818e421876bb6b8bbd6c9",
null,
"b88c5c1977b35b517b0aeae967",
"43fd4727fe5cdb4b5b42818dea7ef8c9"),
new TestVector(17, "7fddb57453c241d03efbed3ac44e371c",
"ee283a3fc75575e33efd4887",
"d5de42b461646c255c87bd2962d3b9a2",
null,
"2ccda4a5415cb91e135c2a0f78c9b2fd",
"b36d1df9b9d5e596f83e8b7f52971cb3"),
new TestVector(18, "9971071059abc009e4f2bd69869db338",
"07a9a95ea3821e9c13c63251",
"f54bc3501fed4f6f6dfb5ea80106df0bd836e6826225b75c0222f6e859b35983",
null,
"0556c159f84ef36cb1602b4526b12009c775611bffb64dc0d9ca9297cd2c6a01",
"7870d9117f54811a346970f1de090c41"),
new TestVector(19, "594157ec4693202b030f33798b07176d",
"49b12054082660803a1df3df",
"3feef98a976a1bd634f364ac428bb59cd51fb159ec1789946918dbd50ea6c9d594a3a31a5269b0da6936c29d063a5fa2cc8a1c",
null,
"c1b7a46a335f23d65b8db4008a49796906e225474f4fe7d39e55bf2efd97fd82d4167de082ae30fa01e465a601235d8d68bc69",
"ba92d3661ce8b04687e8788d55417dc2"),
// 96-bit iv w/ 128-bit tags, 16-byte plain text, 16/20/48/90-byte aad
new TestVector(20, "c939cc13397c1d37de6ae0e1cb7c423c",
"b3d8cc017cbb89b39e0f67e2",
"c3b3c41f113a31b73d9a5cd432103069",
"24825602bd12a984e0092d3e448eda5f",
"93fe7d9e9bfd10348a5606e5cafa7354",
"0032a1dc85f1c9786925a2e71d8272dd"),
new TestVector(21, "d4a22488f8dd1d5c6c19a7d6ca17964c",
"f3d5837f22ac1a0425e0d1d5",
"7b43016a16896497fb457be6d2a54122",
"f1c5d424b83f96c6ad8cb28ca0d20e475e023b5a",
"c2bd67eef5e95cac27e3b06e3031d0a8",
"f23eacf9d1cdf8737726c58648826e9c"),
new TestVector(22, "89850dd398e1f1e28443a33d40162664",
"e462c58482fe8264aeeb7231",
"2805cdefb3ef6cc35cd1f169f98da81a",
"d74e99d1bdaa712864eec422ac507bddbe2b0d4633cd3dff29ce5059b49fe868526c59a2a3a604457bc2afea866e7606",
"ba80e244b7fc9025cd031d0f63677e06",
"d84a8c3eac57d1bb0e890a8f461d1065"),
new TestVector(23, "bd7c5c63b7542b56a00ebe71336a1588",
"87721f23ba9c3c8ea5571abc",
"de15ddbb1e202161e8a79af6a55ac6f3",
"a6ec8075a0d3370eb7598918f3b93e48444751624997b899a87fa6a9939f844e008aa8b70e9f4c3b1a19d3286bf543e7127bfecba1ad17a5ec53fccc26faecacc4c75369498eaa7d706aef634d0009279b11e4ba6c993e5e9ed9",
"41eb28c0fee4d762de972361c863bc80",
"9cb567220d0b252eb97bff46e4b00ff8"),
// 8/1024-bit iv w/ 128-bit tag, no plain text, no aad
new TestVector(24, "1672c3537afa82004c6b8a46f6f0d026",
"05",
null, null, null,
"8e2ad721f9455f74d8b53d3141f27e8e"),
new TestVector(25, "d0f1f4defa1e8c08b4b26d576392027c",
"42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac",
null, null, null,
"7ab49b57ddf5f62c427950111c5c4f0d"),
// 8-bit iv w/ 128-bit tag, 13-byte plain text, 90-byte aad
new TestVector(26, "9f79239f0904eace50784b863e723f6b",
"d9",
"bdb0bb10c87965acd34d146171",
"44db436089327726c5f01139e1f339735c9e85514ccc2f167bad728010fb34a9072a9794c8a5e7361b1d0dbcdc9ac4091e354bb2896561f0486645252e9c78c86beece91bfa4f7cc4a8794ce1f305b1b735efdbf1ed1563c0be0",
"7e5a7c8dadb3f0c7335b4d9d8d",
"6b6ef1f53723a89f3bb7c6d043840717"),
// 1024-bit iv w/ 128-bit tag, 51-byte plain text, 48-byte aad
new TestVector(27, "141f1ce91989b07e7eb6ae1dbd81ea5e",
"49451da24bd6074509d3cebc2c0394c972e6934b45a1d91f3ce1d3ca69e194aa1958a7c21b6f21d530ce6d2cc5256a3f846b6f9d2f38df0102c4791e57df038f6e69085646007df999751e248e06c47245f4cd3b8004585a7470dee1690e9d2d63169a58d243c0b57b3e5b4a481a3e4e8c60007094ef3adea2e8f05dd3a1396f",
"d384305af2388699aa302f510913fed0f2cb63ba42efa8c5c9de2922a2ec2fe87719dadf1eb0aef212b51e74c9c5b934104a43",
"630cf18a91cc5a6481ac9eefd65c24b1a3c93396bd7294d6b8ba323951727666c947a21894a079ef061ee159c05beeb4",
"f4c34e5fbe74c0297313268296cd561d59ccc95bbfcdfcdc71b0097dbd83240446b28dc088abd42b0fc687f208190ff24c0548",
"dbb93bbb56d0439cd09f620a57687f5d"),
};
void executeArray(TestVector tv) throws Exception {
Cipher c = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
try {
System.out.println("Test #" + tv.id + ": byte[].");
c.init(Cipher.ENCRYPT_MODE, tv.key, tv.spec);
c.updateAAD(tv.aad);
byte[] ctPlusTag = c.doFinal(tv.plainText);
c.init(Cipher.DECRYPT_MODE, tv.key, tv.spec);
c.updateAAD(tv.aad);
byte[] pt = c.doFinal(ctPlusTag); // should fail if tag mismatched
// check encryption/decryption results just to be sure
if (!Arrays.equals(tv.plainText, pt)) {
System.out.println("PlainText diff failed for test# " + tv.id);
testFailed = true;
}
int ctLen = tv.cipherText.length;
if (!Arrays.equals(tv.cipherText,
Arrays.copyOf(ctPlusTag, ctLen))) {
System.out.println("CipherText diff failed for test# " + tv.id);
testFailed = true;
}
int tagLen = tv.tag.length;
if (!Arrays.equals
(tv.tag,
Arrays.copyOfRange(ctPlusTag, ctLen, ctLen+tagLen))) {
System.out.println("Tag diff failed for test# " + tv.id);
testFailed = true;
}
} catch (Exception ex) {
// continue testing other test vectors
System.out.println("Failed Test Vector: " + tv);
ex.printStackTrace();
testFailed = true;
}
if (testFailed) {
throw new Exception("Test Failed");
}
}
void executeByteBuffer(TestVector tv, boolean direct, int offset) throws Exception {
Cipher c = Cipher.getInstance("AES/GCM/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
ByteBuffer src;
ByteBuffer ctdst;
ByteBuffer ptdst;
if (direct) {
System.out.print("Test #" + tv.id + ": ByteBuffer Direct.");
src = ByteBuffer.allocateDirect(tv.plainText.length + offset);
ctdst = ByteBuffer.allocateDirect(tv.cipherText.length + tv.tag.length + offset);
ptdst = ByteBuffer.allocateDirect(tv.plainText.length + offset);
} else {
System.out.print("Test #" + tv.id + ": ByteBuffer Heap.");
src = ByteBuffer.allocate(tv.plainText.length + offset);
ctdst = ByteBuffer.allocate(tv.cipherText.length + tv.tag.length + offset);
ptdst = ByteBuffer.allocate(tv.plainText.length + offset);
}
byte[] plainText;
if (offset > 0) {
System.out.println(" offset = " + offset);
plainText = new byte[tv.plainText.length + offset];
System.arraycopy(tv.plainText, 0, plainText, offset,
tv.plainText.length);
} else {
System.out.println();
plainText = tv.plainText;
}
src.put(plainText);
src.position(offset);
ctdst.position(offset);
ctdst.mark();
ptdst.position(offset);
ptdst.mark();
try {
c.init(Cipher.ENCRYPT_MODE, tv.key, tv.spec);
c.updateAAD(tv.aad);
c.doFinal(src, ctdst);
ctdst.reset();
ByteBuffer tag = ctdst.duplicate();
tag.position(tag.limit() - tv.tag.length);
c.init(Cipher.DECRYPT_MODE, tv.key, tv.spec);
c.updateAAD(tv.aad);
c.doFinal(ctdst, ptdst); // should fail if tag mismatched
ptdst.reset();
// check encryption/decryption results just to be sure
if (ptdst.compareTo(ByteBuffer.wrap(tv.plainText)) != 0) {
System.out.println("\t PlainText diff failed for test# " + tv.id);
testFailed = true;
}
ctdst.reset();
ctdst.limit(ctdst.limit() - tv.tag.length);
if (ctdst.compareTo(ByteBuffer.wrap(tv.cipherText)) != 0) {
System.out.println("\t CipherText diff failed for test# " + tv.id);
testFailed = true;
}
int mismatch = 0;
for (int i = 0; i < tv.tag.length; i++) {
mismatch |= tag.get() ^ tv.tag[i];
}
if (mismatch != 0) {
System.out.println("\t Tag diff failed for test# " + tv.id);
testFailed = true;
}
} catch (Exception ex) {
// continue testing other test vectors
System.out.println("\t Failed Test Vector ( #" + tv.id + ") : " + tv);
ex.printStackTrace();
}
}
public static void main (String[] args) throws Exception {
TestKATForGCM test = new TestKATForGCM();
for (TestVector tv : testValues) {
test.executeArray(tv);
test.executeByteBuffer(tv, false, 0);
test.executeByteBuffer(tv, true, 0);
test.executeByteBuffer(tv, false, 2);
test.executeByteBuffer(tv, true, 2);
}
if (!testFailed) {
System.out.println("Tests passed");
}
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2019, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 8180392
* @summary Ensure SunJCE provider throws exception for unsupported modes
* and padding combinations
*/
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.*;
public class TestNoPaddingModes {
// SunJCE only supports NoPadding with following modes
private static final String[] MODES = {
"CTR", "CTS", "GCM"
};
private static final String[] PADDINGS = {
"PKCS5Padding", "ISO10126Padding"
};
public static void main(String[] args) throws Exception {
Provider p = Security.getProvider(
System.getProperty("test.provider.name", "SunJCE"));
String transformation;
for (String mode : MODES) {
for (String padding : PADDINGS) {
transformation = "AES/" + mode + "/" + padding;
System.out.println("Test using " + transformation);
try {
Cipher c = Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
throw new RuntimeException("=> Fail, no exception thrown");
} catch (NoSuchAlgorithmException | NoSuchPaddingException ex) {
System.out.println("=> Expected ex: " + ex);
}
try {
Cipher c = Cipher.getInstance(transformation, p);
throw new RuntimeException("=> Fail, no exception thrown");
} catch (NoSuchAlgorithmException | NoSuchPaddingException ex) {
System.out.println("=> Expected ex: " + ex);
}
}
}
System.out.println("Test Passed");
}
}

View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2014, 2024, 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.
*
* 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.
*/
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidParameterSpecException;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.GCMParameterSpec;
/**
* @test
* @bug 8043836
* @summary Test AES encryption with no padding. Expect the original data length
* is the same as the encrypted data.
* @key randomness
*/
public class TestNonexpanding {
private static final String ALGORITHM = "AES";
private static final String PROVIDER =
System.getProperty("test.provider.name", "SunJCE");
private static final String[] MODES = { "ECb", "CbC", "OFB", "OFB150",
"cFB", "CFB7", "cFB8", "cFB16", "cFB24", "cFB32", "Cfb40", "cfB48",
"cfB56", "cfB64", "cfB72", "cfB80", "cfB88", "cfB96", "cfb104",
"cfB112", "cfB120", "GCM" };
private static final String PADDING = "NoPadding";
private static final int KEY_LENGTH = 128;
public static void main(String argv[]) throws Exception {
TestNonexpanding test = new TestNonexpanding();
for (String mode : MODES) {
test.runTest(ALGORITHM, mode, PADDING);
}
}
public void runTest(String algo, String mo, String pad) throws Exception {
Cipher ci = null;
SecretKey key = null;
try {
// Initialization
Random rdm = new Random();
byte[] plainText = new byte[128];
rdm.nextBytes(plainText);
ci = Cipher.getInstance(algo + "/" + mo + "/" + pad, PROVIDER);
KeyGenerator kg = KeyGenerator.getInstance(algo, PROVIDER);
kg.init(KEY_LENGTH);
key = kg.generateKey();
// encrypt
ci.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
int offset = ci.update(plainText, 0, plainText.length, cipherText,
0);
ci.doFinal(cipherText, offset);
// Comparison
if (!(plainText.length == cipherText.length)) {
// The result of encryption in GCM is a combination of an
// authentication tag and cipher text.
if (mo.equalsIgnoreCase("GCM")) {
GCMParameterSpec spec = ci.getParameters().getParameterSpec(GCMParameterSpec.class);
int cipherTextLength = cipherText.length - spec.getTLen()
/ 8;
if (plainText.length == cipherTextLength) {
return;
}
}
System.out.println("Original length: " + plainText.length);
System.out.println("Cipher text length: " + cipherText.length);
throw new RuntimeException("Test failed!");
}
} catch (NoSuchAlgorithmException e) {
//CFB7 and OFB150 are for negative testing
if (!mo.equalsIgnoreCase("CFB7") && !mo.equalsIgnoreCase("OFB150")) {
System.out.println("Unexpected NoSuchAlgorithmException with mode: "
+ mo);
throw new RuntimeException("Test failed!");
}
} catch ( NoSuchProviderException | NoSuchPaddingException
| InvalidKeyException | InvalidParameterSpecException
| ShortBufferException | IllegalBlockSizeException
| BadPaddingException e) {
System.out.println("Test failed!");
throw e;
}
}
}

View file

@ -0,0 +1,140 @@
/*
* Copyright (c) 2014, 2024, 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.
*
* 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.
*/
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Random;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
/**
* @test
* @bug 8043836
* @summary Test AES ciphers with different modes and padding schemes (ECB mode
* doesn't use IV). The test tries 3 different read methods of
* CipherInputStream.
* @key randomness
*/
public class TestSameBuffer {
private static final String ALGORITHM = "AES";
private static final String PROVIDER =
System.getProperty("test.provider.name", "SunJCE");
private static final String[] MODES = { "ECb", "CbC", "OFB", "CFB150",
"cFB", "CFB7", " cFB8", "cFB16", "cFB24", "cFB32", "Cfb40",
"cfB48", " cfB56", "cfB64", "cfB72", "cfB80", "cfB88", "cfB96",
"cfb104", "cfB112", "cfB120" };
private static final String PADDING = "NoPadding";
private static final int KEY_LENGTH = 128;
public static void main(String argv[]) throws Exception {
TestSameBuffer test = new TestSameBuffer();
for (String mode : MODES) {
test.runTest(ALGORITHM, mode, PADDING);
}
}
public void runTest(String algo, String mo, String pad) throws Exception {
Cipher ci = null;
byte[] iv = null;
AlgorithmParameterSpec aps = null;
SecretKey key = null;
try {
// Initialization
Random rdm = new Random();
byte[] plainText = new byte[128];
rdm.nextBytes(plainText);
// keep the plain text
byte[] tmpText = new byte[plainText.length];
for (int i = 0; i < plainText.length; i++) {
tmpText[i] = plainText[i];
}
ci = Cipher.getInstance(algo + "/" + mo + "/" + pad, PROVIDER);
KeyGenerator kg = KeyGenerator.getInstance(algo, PROVIDER);
kg.init(KEY_LENGTH);
key = kg.generateKey();
// encrypt
ci.init(Cipher.ENCRYPT_MODE, key);
int offset = ci
.update(plainText, 0, plainText.length, plainText, 0);
ci.doFinal(plainText, offset);
if (!mo.equalsIgnoreCase("ECB")) {
iv = ci.getIV();
aps = new IvParameterSpec(iv);
} else {
aps = null;
}
ci.init(Cipher.DECRYPT_MODE, key, aps);
byte[] recoveredText = new byte[ci.getOutputSize(plainText.length)];
ci.doFinal(plainText, 0, plainText.length, recoveredText);
// Comparison
if (!java.util.Arrays.equals(tmpText, recoveredText)) {
System.out.println("Original: ");
dumpBytes(plainText);
System.out.println("Recovered: ");
dumpBytes(recoveredText);
throw new RuntimeException(
"Original text is not equal with recovered text, with mode:"
+ mo);
}
} catch (NoSuchAlgorithmException e) {
//CFB7 and CFB150 are for negative testing
if (!mo.equalsIgnoreCase("CFB7") && !mo.equalsIgnoreCase("CFB150")) {
System.out.println("Unexpected NoSuchAlgorithmException with mode: "
+ mo);
throw new RuntimeException("Test failed!");
}
} catch (NoSuchProviderException | NoSuchPaddingException
| InvalidKeyException | InvalidAlgorithmParameterException
| ShortBufferException | IllegalBlockSizeException
| BadPaddingException e) {
System.out.println("Test failed!");
throw e;
}
}
private void dumpBytes(byte[] bytes) {
for (byte b : bytes) {
System.out.print(Integer.toHexString(b));
}
System.out.println();
}
}

View file

@ -0,0 +1,197 @@
/*
* Copyright (c) 2004, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4979126
* @summary Ensure update()/doFinal() matches javadoc description
* when ShortBufferException is thrown.
* @author Valerie Peng
*/
import java.util.Arrays;
import java.security.*;
import java.security.spec.*;
import java.math.BigInteger;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.Provider;
public class TestShortBuffer {
private static final String ALGO = "AES";
private static final String[] MODES = {
"ECB", "CBC", "PCBC", "CFB16", "OFB8"
};
private static final SecretKey KEY =
new SecretKeySpec(new byte[16], ALGO);
private static byte[] SHORTBUFFER = new byte[1];
private static final byte[] PLAINTEXT = new byte[30];
static {
PLAINTEXT[0] = (byte)0x15;
};
private Cipher ci = null;
private byte[] in = null;
private byte[] expected = null;
private byte[] out = null;
private int outOffset = 0;
private TestShortBuffer(Cipher ci) {
this.ci = ci;
}
private void init(byte[] in, byte[] expected) {
this.in = (byte[]) in.clone();
this.expected = (byte[]) expected.clone();
this.out = new byte[expected.length];
this.outOffset = 0;
}
private static void runTest() throws Exception {
// Initialization
for (int i = 0; i < MODES.length; i++) {
System.out.println("===== TESTING MODE " + MODES[i] + " =====");
Cipher ci = Cipher.getInstance(ALGO+"/"+MODES[i]+"/PKCS5Padding",
System.getProperty("test.provider.name", "SunJCE"));
TestShortBuffer test = null;
int stored = 0;
AlgorithmParameters params = null;
byte[] cipherText = null;
byte[] shortBuffer = new byte[8];
for (int k = 0; k < 2; k++) {
byte[] expected = null;
switch (k) {
case 0: // Encryption
System.out.println("Testing with Cipher.ENCRYPT_MODE");
ci.init(Cipher.ENCRYPT_MODE, KEY);
cipherText = ci.doFinal(PLAINTEXT);
test = new TestShortBuffer(ci);
test.init(PLAINTEXT, cipherText);
params = ci.getParameters();
break;
case 1: // Decryption
System.out.println("Testing with Cipher.DECRYPT_MODE");
ci.init(Cipher.DECRYPT_MODE, KEY, params);
test = new TestShortBuffer(ci);
test.init(cipherText, PLAINTEXT);
break;
}
int offset = 2 + i*5;
test.testUpdate();
test.testUpdateWithUpdate(offset);
test.testDoFinal();
test.testDoFinalWithUpdate(offset);
}
}
}
private void checkOutput() throws Exception {
if (!Arrays.equals(out, expected)) {
System.out.println("got: " + new BigInteger(out));
System.out.println("expect: " + new BigInteger(expected));
throw new Exception("Generated different outputs");
}
}
private void testUpdate() throws Exception {
outOffset = 0;
int stored = 0;
try {
stored = ci.update(in, 0, in.length, SHORTBUFFER);
throw new Exception("Should throw ShortBufferException!");
} catch (ShortBufferException sbe) {
System.out.println("Expected SBE thrown....");
// retry with a large-enough buffer according to javadoc
stored = ci.update(in, 0, in.length, out);
stored = ci.doFinal(out, outOffset += stored);
if (out.length != (stored + outOffset)) {
throw new Exception("Wrong number of output bytes");
}
}
checkOutput();
}
private void testUpdateWithUpdate(int offset) throws Exception {
outOffset = 0;
int stored = 0;
byte[] out1 = ci.update(in, 0, offset);
if (out1 != null) {
System.arraycopy(out1, 0, out, 0, out1.length);
outOffset += out1.length;
}
try {
stored = ci.update(in, offset, in.length-offset, SHORTBUFFER);
throw new Exception("Should throw ShortBufferException!");
} catch (ShortBufferException sbe) {
System.out.println("Expected SBE thrown....");
// retry with a large-enough buffer according to javadoc
stored = ci.update(in, offset, in.length-offset,
out, outOffset);
stored = ci.doFinal(out, outOffset+=stored);
if (out.length != (stored + outOffset)) {
throw new Exception("Wrong number of output bytes");
}
}
checkOutput();
}
private void testDoFinal() throws Exception {
outOffset = 0;
int stored = 0;
try {
stored = ci.doFinal(in, 0, in.length, SHORTBUFFER);
throw new Exception("Should throw ShortBufferException!");
} catch (ShortBufferException sbe) {
System.out.println("Expected SBE thrown....");
// retry with a large-enough buffer according to javadoc
stored = ci.doFinal(in, 0, in.length, out, 0);
if (out.length != stored) {
throw new Exception("Wrong number of output bytes");
}
}
checkOutput();
}
private void testDoFinalWithUpdate(int offset) throws Exception {
outOffset = 0;
int stored = 0;
byte[] out1 = ci.update(in, 0, offset);
if (out1 != null) {
System.arraycopy(out1, 0, out, 0, out1.length);
outOffset += out1.length;
}
try {
stored = ci.doFinal(in, offset, in.length-offset, SHORTBUFFER);
throw new Exception("Should throw ShortBufferException!");
} catch (ShortBufferException sbe) {
System.out.println("Expected SBE thrown....");
// retry with a large-enough buffer according to javadoc
stored = ci.doFinal(in, offset, in.length-offset,
out, outOffset);
if (out.length != (stored + outOffset)) {
throw new Exception("Wrong number of output bytes");
}
}
checkOutput();
}
public static void main(String[] argv) throws Exception {
runTest();
System.out.println("Test Passed");
}
}

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 1998, 2021, 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.
*
* 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.
*/
/*
* @test
* @bug 0000000
* @library ../UTIL
* @build TestUtil
* @run main BlowfishTestVector
* @summary Known Answer Test for Blowfish cipher with ECB mode
* @author Jan Luehe
*/
import java.security.*;
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class BlowfishTestVector {
// test vector #1 (checking for the "signed" bug)
// (ECB mode)
private static final byte[] TEST_KEY_1 = new byte[] {
(byte)0x1c, (byte)0x58, (byte)0x7f, (byte)0x1c,
(byte)0x13, (byte)0x92, (byte)0x4f, (byte)0xef
};
private static final byte[] TV_P1 = new byte[] {
(byte)0x30, (byte)0x55, (byte)0x32, (byte)0x28,
(byte)0x6d, (byte)0x6f, (byte)0x29, (byte)0x5a
};
private static final byte[] TV_C1 = new byte[] {
(byte)0x55, (byte)0xcb, (byte)0x37, (byte)0x74,
(byte)0xd1, (byte)0x3e, (byte)0xf2, (byte)0x01
};
// test vector #2 (offical vector by Bruce Schneier)
// (ECB mode)
private static final String S_TEST_KEY_2 = "Who is John Galt?";
private static final byte[] TV_P2 = new byte[] {
(byte)0xfe, (byte)0xdc, (byte)0xba, (byte)0x98,
(byte)0x76, (byte)0x54, (byte)0x32, (byte)0x10
};
private static final byte[] TV_C2 = new byte[] {
(byte)0xcc, (byte)0x91, (byte)0x73, (byte)0x2b,
(byte)0x80, (byte)0x22, (byte)0xf6, (byte)0x84
};
public static void main(String[] argv) throws Exception {
String transformation = "Blowfish/ECB/NoPadding";
Cipher cipher = Cipher.getInstance(transformation, "SunJCE");
int MAX_KEY_SIZE = Cipher.getMaxAllowedKeyLength(transformation);
//
// test 1
//
if (TEST_KEY_1.length*8 <= MAX_KEY_SIZE) {
SecretKey sKey = new SecretKeySpec(TEST_KEY_1, "Blowfish");
try {
cipher.init(Cipher.ENCRYPT_MODE, sKey);
byte[] c1 = cipher.doFinal(TV_P1);
if (!Arrays.equals(c1, TV_C1))
throw new Exception("Encryption (Test vector 1) failed");
cipher.init(Cipher.DECRYPT_MODE, sKey);
byte[] p1 = cipher.doFinal(c1);
if (!Arrays.equals(p1, TV_P1))
throw new Exception("Decryption (Test vector 1) failed");
} catch (SecurityException se) {
TestUtil.handleSE(se);
}
}
//
// test 2
//
byte[] testKey2 = S_TEST_KEY_2.getBytes();
if (testKey2.length*8 <= MAX_KEY_SIZE) {
SecretKey sKey = new SecretKeySpec(testKey2, "Blowfish");
try {
cipher.init(Cipher.ENCRYPT_MODE, sKey);
byte[] c2 = cipher.doFinal(TV_P2);
if (!Arrays.equals(c2, TV_C2))
throw new Exception("Encryption (Test vector 2) failed");
cipher.init(Cipher.DECRYPT_MODE, sKey);
byte[] p2 = cipher.doFinal(c2);
if (!Arrays.equals(p2, TV_P2))
throw new Exception("Decryption (Test vector 2) failed");
} catch (SecurityException se) {
TestUtil.handleSE(se);
}
}
System.out.println("Test passed");
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2015, 2019, 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.
*
* 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.
*/
import java.security.NoSuchAlgorithmException;
/*
* @test
* @bug 8048601
* @library ../
* @summary Test Blowfish cipher with different MODES and padding
*/
public class TestCipherBlowfish extends TestCipher {
TestCipherBlowfish(String[] modes, String[] paddings) throws NoSuchAlgorithmException {
super("Blowfish", modes, paddings, 32, 448);
}
public static void main(String[] args) throws Exception {
new TestCipherBlowfish(new String[]{ "CBC", "ECB", "PCBC",
//CFBx
"CFB", "CFB8", "CFB16", "CFB24", "CFB32", "CFB40",
"CFB48", "CFB56", "CFB64",
//OFBx
"OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
"OFB48", "OFB56", "OFB64"},
new String[]{ "NoPaDDing", "PKCS5Padding"}).runAll();
new TestCipherBlowfish(new String[]{ "CTR", "CTS" },
new String[]{ "NoPaDDing" }).runAll();
}
}

View file

@ -0,0 +1,190 @@
/*
* Copyright (c) 2002, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 4688768
* @library ../UTIL
* @build TestUtil
* @run main CounterMode
* @summary Verify that CTR mode works as expected
* @author Andreas Sterbenz
*/
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class CounterMode {
private final static byte[] toByteArray(String s) {
char[] c = s.toCharArray();
byte[] t = new byte[c.length / 2];
int n = 0;
int d1 = -1;
int d2 = -1;
for (int i = 0; i < c.length; i++) {
char ch = c[i];
if (d1 == -1) {
d1 = Character.digit(ch, 16);
} else {
d2 = Character.digit(ch, 16);
if (d2 != -1) {
t[n++] = (byte)((d1 << 4) | d2);
d1 = -1;
d2 = -1;
}
}
}
if (d1 != -1) {
throw new RuntimeException();
}
if (n == t.length) {
return t;
}
byte[] b = new byte[n];
System.arraycopy(t, 0, b, 0, n);
return b;
}
private final static String[] ALGORITHM = {
"AES",
"AES",
"AES",
"AES",
"AES",
"DES",
"DES",
"DESede",
"DESede",
"Blowfish",
"Blowfish",
};
private final static byte[][] KEYS = {
toByteArray("2b7e151628aed2a6abf7158809cf4f3c"),
toByteArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"),
toByteArray("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
toByteArray("2b7e151628aed2a6abf7158809cf4f3c"),
toByteArray("2b7e151628aed2a6abf7158809cf4f3c"),
toByteArray("2b7e151628aed2a6"),
toByteArray("874d6191b620e326"),
toByteArray("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"),
toByteArray("874d6191b620e3261bef6864990db6ce9806f66b7970fdff"),
toByteArray("2b7e151628aed2a6abf7158809cf4f3c"),
toByteArray("874d6191b620e3261bef6864990db6ce"),
};
private final static byte[][] IVS = {
toByteArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
toByteArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
toByteArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
toByteArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
toByteArray("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
toByteArray("fffffffffffffffd"),
toByteArray("f0f1f2f3f4f5f6f7"),
toByteArray("f0f1f2f3f4f5f6f7"),
toByteArray("f0f1f2f3f4f5f6ff"),
toByteArray("f0f1f2f3f4f5f6f7"),
toByteArray("f0f1f2f3f4f5f6ff"),
};
private final static byte[][] PLAIN = {
toByteArray("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"),
toByteArray("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"),
toByteArray("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"),
toByteArray("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c37"),
toByteArray(""),
toByteArray("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"),
toByteArray("6bc1bee22e409f96"),
toByteArray("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"),
toByteArray("6bc1bee22e409f96e9"),
toByteArray("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"),
toByteArray("6bc1bee22e409f"),
};
private final static byte[][] CIPHER = {
toByteArray("874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"),
toByteArray("1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e941e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050"),
toByteArray("601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c52b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6"),
toByteArray("874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009c"),
toByteArray(""),
toByteArray("79:62:2c:42:59:8e:9a:1a:e3:da:3d:7c:88:4f:0a:d2:eb:1a:e2:27:b0:d7:16:f6:6d:8d:50:fe:8b:9f:87:a7:ba:83:65:48:5b:87:12:07:d0:3f:3d:f0:b2:c8:98:e9:bb:a0:ad:35:98:e8:4f:d8:ef:91:85:2c:55:c0:b0:b9"),
toByteArray("79:5e:90:a6:35:9d:1e:b2"),
toByteArray("0a:ce:b5:1e:20:74:2e:29:17:28:55:d6:c9:28:62:c3:43:a5:da:30:90:9f:8f:46:60:3d:b6:5c:b6:bc:21:52:06:2f:6f:b4:14:0d:ef:23:e2:99:fd:4b:dc:65:ee:6a:50:76:5b:86:43:65:56:ee:1a:7a:25:07:43:b4:f0:88"),
toByteArray("12:06:8f:ae:bb:47:a7:68:8b"),
toByteArray("ac:92:83:dd:79:f3:c2:36:0c:da:06:bd:ed:69:ca:47:42:2e:68:11:5e:6b:63:56:3e:87:b0:be:98:17:42:7d:8b:4a:5b:be:af:0c:2b:f0:1c:1c:62:60:b9:2c:69:04:ca:c9:23:d2:08:9d:8d:57:7f:61:f7:e6:79:83:ae:89"),
toByteArray("65:ff:ee:6b:64:9e:a0"),
};
private static String toString(byte[] b) {
StringBuffer sb = new StringBuffer(b.length * 3);
for (int i = 0; i < b.length; i++) {
int k = b[i] & 0xff;
if (i != 0) {
sb.append(':');
}
sb.append(Character.forDigit(k >> 4, 16));
sb.append(Character.forDigit(k & 0xf, 16));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < KEYS.length; i++) {
try {
String alg = ALGORITHM[i];
int MAX_KEYSIZE = Cipher.getMaxAllowedKeyLength(alg);
if (KEYS[i].length*8 > MAX_KEYSIZE) {
// skip tests using keys whose length exceeds
// what's configured in jce jurisdiction policy files.
continue;
}
System.out.println("Running test " + i + " (" + alg + ")");
Cipher cipher = Cipher.getInstance(alg + "/CTR/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
SecretKeySpec key = new SecretKeySpec(KEYS[i], alg);
IvParameterSpec iv = new IvParameterSpec(IVS[i]);
byte[] plainText = PLAIN[i];
byte[] cipherText = CIPHER[i];
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] enc = cipher.doFinal(plainText);
if (Arrays.equals(cipherText, enc) == false) {
System.out.println("plain: " + toString(PLAIN[i]));
System.out.println("cipher: " + toString(CIPHER[i]));
System.out.println("actual: " + toString(enc));
throw new RuntimeException("Encryption failure for test " + i);
}
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] dec = cipher.doFinal(cipherText);
if (Arrays.equals(plainText, dec) == false) {
throw new RuntimeException("Decryption failure for test " + i);
}
} catch (SecurityException ex) {
TestUtil.handleSE(ex);
}
}
System.out.println("Done");
}
}

View file

@ -0,0 +1,367 @@
/*
* Copyright (c) 2005, 2024, 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.
*
* 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.
*/
/*
* @test
* @bug 5083253
* @run main CTSMode
* @summary Verify that CTR mode works as expected
* @author Valerie Peng
*/
import java.util.*;
import java.security.AlgorithmParameters;
import javax.crypto.*;
import javax.crypto.spec.*;
public class CTSMode {
private final static byte[] toByteArray(String s) {
char[] c = s.toCharArray();
byte[] t = new byte[c.length / 2];
int n = 0;
int d1 = -1;
int d2 = -1;
for (int i = 0; i < c.length; i++) {
char ch = c[i];
if (d1 == -1) {
d1 = Character.digit(ch, 16);
} else {
d2 = Character.digit(ch, 16);
if (d2 != -1) {
t[n++] = (byte)((d1 << 4) | d2);
d1 = -1;
d2 = -1;
}
}
}
if (d1 != -1) {
throw new RuntimeException();
}
if (n == t.length) {
return t;
}
byte[] b = new byte[n];
System.arraycopy(t, 0, b, 0, n);
return b;
}
private final static SecretKey KEY1 =
new SecretKeySpec(toByteArray("636869636b656e207465726979616b69"),
"AES");
private final static IvParameterSpec IV1 =
new IvParameterSpec(new byte[16]);
/*
* Use test vectors, i.e. PLAIN1 and CIPHER1, from the appendix B
* of RFC 3962 "Advanced Encryption Standard (AES) Encryption for
* Kerberos 5".
*/
private final static byte[][] PLAIN1 = {
toByteArray("4920776f756c64206c696b652074686520"),
toByteArray("4920776f756c64206c696b6520746865" +
"2047656e6572616c20476175277320"),
toByteArray("4920776f756c64206c696b6520746865" +
"2047656e6572616c2047617527732043"),
toByteArray("4920776f756c64206c696b6520746865" +
"2047656e6572616c2047617527732043" +
"6869636b656e2c20706c656173652c"),
toByteArray("4920776f756c64206c696b6520746865" +
"2047656e6572616c2047617527732043" +
"6869636b656e2c20706c656173652c20"),
toByteArray("4920776f756c64206c696b6520746865" +
"2047656e6572616c2047617527732043" +
"6869636b656e2c20706c656173652c20" +
"616e6420776f6e746f6e20736f75702e")
};
private final static byte[][] CIPHER1 = {
toByteArray("c6353568f2bf8cb4d8a580362da7ff7f97"),
toByteArray("fc00783e0efdb2c1d445d4c8eff7ed22" +
"97687268d6ecccc0c07b25e25ecfe5"),
toByteArray("39312523a78662d5be7fcbcc98ebf5a8" +
"97687268d6ecccc0c07b25e25ecfe584"),
toByteArray("97687268d6ecccc0c07b25e25ecfe584" +
"b3fffd940c16a18c1b5549d2f838029e" +
"39312523a78662d5be7fcbcc98ebf5"),
toByteArray("97687268d6ecccc0c07b25e25ecfe584" +
"9dad8bbb96c4cdc03bc103e1a194bbd8" +
"39312523a78662d5be7fcbcc98ebf5a8"),
toByteArray("97687268d6ecccc0c07b25e25ecfe584" +
"39312523a78662d5be7fcbcc98ebf5a8" +
"4807efe836ee89a526730dbc2f7bc840" +
"9dad8bbb96c4cdc03bc103e1a194bbd8"),
};
private final static byte[] IV2_SRC =
toByteArray("11223344556677880011223344556677");
private final static String[] ALGORITHMS2 = {
"DES", "DESede", "Blowfish", "AES"
};
private final static int[] KEYSIZES2 = {
8, 24, 16, 16
};
private static String toString(byte[] b) {
StringBuffer sb = new StringBuffer(b.length * 3);
for (int i = 0; i < b.length; i++) {
int k = b[i] & 0xff;
if (i != 0) {
sb.append(':');
}
sb.append(Character.forDigit(k >> 4, 16));
sb.append(Character.forDigit(k & 0xf, 16));
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
test1();
test2();
test3();
}
/**
* Test with the test vectors and see if results match.
*/
private static void test1() throws Exception {
for (int i = 0; i < PLAIN1.length; i++) {
String algo = KEY1.getAlgorithm();
int MAX_KEYSIZE = Cipher.getMaxAllowedKeyLength(algo);
if (KEY1.getEncoded().length > MAX_KEYSIZE) {
// skip tests using keys whose length exceeds
// what's configured in jce jurisdiction policy files.
continue;
}
System.out.println("Running test1_" + i + " (" + algo + ")");
Cipher cipher = Cipher.getInstance(algo+ "/CTS/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
byte[] plainText = PLAIN1[i];
byte[] cipherText = CIPHER1[i];
cipher.init(Cipher.ENCRYPT_MODE, KEY1, IV1);
byte[] enc = cipher.doFinal(plainText);
if (Arrays.equals(cipherText, enc) == false) {
System.out.println("plain: " + toString(plainText));
System.out.println("cipher: " + toString(cipherText));
System.out.println("actual: " + toString(enc));
throw new RuntimeException("Encryption failure for test " + i);
}
cipher.init(Cipher.DECRYPT_MODE, KEY1, IV1);
byte[] dec = cipher.doFinal(cipherText);
if (Arrays.equals(plainText, dec) == false) {
System.out.println("cipher: " + toString(cipherText));
System.out.println("plain: " + toString(plainText));
System.out.println("actual: " + toString(enc));
throw new RuntimeException("Decryption failure for test " + i);
}
}
}
/**
* Test with a combination of update/doFinal calls and make
* sure that same data is recovered after decryption.
*/
private static void test2() throws Exception {
for (int i = 0; i < ALGORITHMS2.length; i++) {
String algo = ALGORITHMS2[i];
System.out.println("Running test2_" + i + " (" + algo + ")");
int keySize = KEYSIZES2[i];
int MAX_KEYSIZE = Cipher.getMaxAllowedKeyLength(algo);
if (keySize > MAX_KEYSIZE) {
// skip tests using keys whose length exceeds
// what's configured in jce jurisdiction policy files.
continue;
}
Cipher cipher =
Cipher.getInstance(algo+"/CTS/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
int blockSize = cipher.getBlockSize();
SecretKeySpec key = new SecretKeySpec(new byte[keySize], algo);
// Make sure encryption works for inputs with valid length
byte[] plainText = PLAIN1[3];
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = new byte[plainText.length];
int firstPartLen = blockSize + 1;
int processed1 = cipher.update(plainText, 0, firstPartLen,
cipherText, 0);
int processed2 = cipher.doFinal(plainText, firstPartLen,
plainText.length-firstPartLen,
cipherText, processed1);
AlgorithmParameters params = cipher.getParameters();
if ((processed1 + processed2) != plainText.length) {
System.out.println("processed1 = " + processed1);
System.out.println("processed2 = " + processed2);
System.out.println("total length = " + plainText.length);
throw new RuntimeException("Encryption failure for test " + i);
}
// Make sure IllegalBlockSizeException is thrown for inputs
// with less-than-a-block length
try {
cipher.doFinal(new byte[blockSize-1]);
throw new RuntimeException("Expected IBSE is not thrown");
} catch (IllegalBlockSizeException ibse) {
}
// Make sure data is encrypted as in CBC mode for inputs
// which is exactly one block long
IvParameterSpec iv2 = new IvParameterSpec(IV2_SRC, 0, blockSize);
cipher.init(Cipher.ENCRYPT_MODE, key, iv2);
Cipher cipher2 =
Cipher.getInstance(algo+"/CBC/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
cipher2.init(Cipher.ENCRYPT_MODE, key, iv2);
byte[] eout = cipher.doFinal(IV2_SRC, 0, blockSize);
byte[] eout2 = cipher2.doFinal(IV2_SRC, 0, blockSize);
if (!Arrays.equals(eout, eout2)) {
throw new RuntimeException("Different encryption output " +
"for CBC and CTS");
}
// Make sure decryption works for inputs with valid length
cipher.init(Cipher.DECRYPT_MODE, key, params);
byte[] recoveredText =
new byte[cipher.getOutputSize(cipherText.length)];
processed1 = cipher.update(cipherText, 0, firstPartLen,
recoveredText, 0);
processed2 = cipher.update(cipherText, firstPartLen,
cipherText.length-firstPartLen,
recoveredText, processed1);
int processed3 =
cipher.doFinal(recoveredText, processed1+processed2);
if ((processed1 + processed2 + processed3) != plainText.length) {
System.out.println("processed1 = " + processed1);
System.out.println("processed2 = " + processed2);
System.out.println("processed3 = " + processed3);
System.out.println("total length = " + plainText.length);
throw new RuntimeException("Decryption failure for test " + i);
}
if (Arrays.equals(plainText, recoveredText) == false) {
System.out.println("plain: " + toString(plainText));
System.out.println("recovered: " + toString(recoveredText));
throw new RuntimeException("Decryption failure for test " + i);
}
// Make sure IllegalBlockSizeException is thrown for inputs
// with less-than-a-block length
try {
cipher.doFinal(new byte[blockSize-1]);
throw new RuntimeException("Expected IBSE is not thrown");
} catch (IllegalBlockSizeException ibse) {
}
// Make sure data is decrypted as in CBC mode for inputs
// which is exactly one block long
cipher.init(Cipher.DECRYPT_MODE, key, iv2);
cipher2.init(Cipher.DECRYPT_MODE, key, iv2);
byte[] dout = cipher.doFinal(eout);
byte[] dout2 = cipher2.doFinal(eout2);
if (!Arrays.equals(dout, dout2)) {
throw new RuntimeException("Different decryption output " +
"for CBC and CTS");
}
}
}
/**
* Test with a shortBuffer and see if encryption/decryption
* still works correctly afterwards.
*/
private static void test3() throws Exception {
// Skip PLAIN1[0, 1, 2] due to their lengths
for (int i = 3; i < PLAIN1.length; i++) {
String algo = KEY1.getAlgorithm();
System.out.println("Running test3_" + i + " (" + algo + ")");
int MAX_KEYSIZE = Cipher.getMaxAllowedKeyLength(algo);
if (KEY1.getEncoded().length > MAX_KEYSIZE) {
// skip tests using keys whose length exceeds
// what's configured in jce jurisdiction policy files.
continue;
}
Cipher cipher =
Cipher.getInstance(algo+ "/CTS/NoPadding",
System.getProperty("test.provider.name", "SunJCE"));
byte[] plainText = PLAIN1[i];
byte[] cipherText = CIPHER1[i];
byte[] enc = new byte[plainText.length];
cipher.init(Cipher.ENCRYPT_MODE, KEY1, IV1);
int halfInput = plainText.length/2;
int processed1 = cipher.update(plainText, 0, halfInput,
enc, 0);
try {
cipher.doFinal(plainText, halfInput,
plainText.length-halfInput,
new byte[1], 0);
throw new RuntimeException("Expected Exception is not thrown");
} catch (ShortBufferException sbe) {
// expected exception thrown; retry
int processed2 =
cipher.doFinal(plainText, halfInput,
plainText.length-halfInput,
enc, processed1);
if ((processed1 + processed2) != enc.length) {
System.out.println("processed1 = " + processed1);
System.out.println("processed2 = " + processed2);
System.out.println("total length = " + enc.length);
throw new RuntimeException("Encryption length check " +
"failed");
}
}
if (Arrays.equals(cipherText, enc) == false) {
System.out.println("plain: " + toString(plainText));
System.out.println("cipher: " + toString(cipherText));
System.out.println("actual: " + toString(enc));
throw new RuntimeException("Encryption failure for test " + i);
}
cipher.init(Cipher.DECRYPT_MODE, KEY1, IV1);
byte[] dec =
new byte[cipher.getOutputSize(cipherText.length)];
processed1 = cipher.update(cipherText, 0, halfInput,
dec, 0);
try {
cipher.update(cipherText, halfInput,
cipherText.length-halfInput,
new byte[1], 0);
throw new RuntimeException("Expected Exception is not thrown");
} catch (ShortBufferException sbe) {
// expected exception thrown; retry
int processed2 = cipher.update(cipherText, halfInput,
cipherText.length-halfInput,
dec, processed1);
int processed3 =
cipher.doFinal(dec, processed1+processed2);
if ((processed1 + processed2 + processed3) != dec.length) {
System.out.println("processed1 = " + processed1);
System.out.println("processed2 = " + processed2);
System.out.println("processed3 = " + processed3);
System.out.println("total length = " + dec.length);
throw new RuntimeException("Decryption length check " +
"failed");
}
}
if (Arrays.equals(plainText, dec) == false) {
System.out.println("cipher: " + toString(cipherText));
System.out.println("plain: " + toString(plainText));
System.out.println("actualD: " + toString(dec));
throw new RuntimeException("Decryption failure for test " + i);
}
}
}
}

View file

@ -0,0 +1,495 @@
/*
* Copyright (c) 2018, 2021, 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.
*
* 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.
*/
/**
* @test
* @bug 8153029
* @library /test/lib
* @build jdk.test.lib.Convert
* @run main ChaCha20KAT
* @summary ChaCha20 Cipher Implementation (KAT)
*/
import java.util.*;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.spec.ChaCha20ParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.AEADBadTagException;
import java.nio.ByteBuffer;
import jdk.test.lib.Convert;
public class ChaCha20KAT {
public static class TestData {
public TestData(String name, String keyStr, String nonceStr, int ctr,
int dir, String inputStr, String aadStr, String outStr) {
testName = Objects.requireNonNull(name);
HexFormat hex = HexFormat.of();
key = hex.parseHex(Objects.requireNonNull(keyStr));
nonce = hex.parseHex(Objects.requireNonNull(nonceStr));
if ((counter = ctr) < 0) {
throw new IllegalArgumentException(
"counter must be 0 or greater");
}
direction = dir;
if ((direction != Cipher.ENCRYPT_MODE) &&
(direction != Cipher.DECRYPT_MODE)) {
throw new IllegalArgumentException(
"Direction must be ENCRYPT_MODE or DECRYPT_MODE");
}
input = hex.parseHex(Objects.requireNonNull(inputStr));
aad = (aadStr != null) ? hex.parseHex(aadStr) : null;
expOutput = hex.parseHex(Objects.requireNonNull(outStr));
}
public final String testName;
public final byte[] key;
public final byte[] nonce;
public final int counter;
public final int direction;
public final byte[] input;
public final byte[] aad;
public final byte[] expOutput;
}
public static final List<TestData> testList = new LinkedList<TestData>() {{
add(new TestData("RFC 7539 Sample Test Vector",
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"000000000000004a00000000",
1, Cipher.ENCRYPT_MODE,
"4c616469657320616e642047656e746c656d656e206f662074686520636c6173" +
"73206f66202739393a204966204920636f756c64206f6666657220796f75206f" +
"6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" +
"637265656e20776f756c642062652069742e",
null,
"6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0b" +
"f91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d8" +
"07ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab7793736" +
"5af90bbf74a35be6b40b8eedf2785e42874d"));
add(new TestData("RFC 7539 Test Vector 1 (all zeroes)",
"0000000000000000000000000000000000000000000000000000000000000000",
"000000000000000000000000",
0, Cipher.ENCRYPT_MODE,
"0000000000000000000000000000000000000000000000000000000000000000" +
"0000000000000000000000000000000000000000000000000000000000000000",
null,
"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7" +
"da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586"));
add(new TestData("RFC 7539 Test Vector 2",
"0000000000000000000000000000000000000000000000000000000000000001",
"000000000000000000000002",
1, Cipher.ENCRYPT_MODE,
"416e79207375626d697373696f6e20746f20746865204945544620696e74656e" +
"6465642062792074686520436f6e7472696275746f7220666f72207075626c69" +
"636174696f6e20617320616c6c206f722070617274206f6620616e2049455446" +
"20496e7465726e65742d4472616674206f722052464320616e6420616e792073" +
"746174656d656e74206d6164652077697468696e2074686520636f6e74657874" +
"206f6620616e204945544620616374697669747920697320636f6e7369646572" +
"656420616e20224945544620436f6e747269627574696f6e222e205375636820" +
"73746174656d656e747320696e636c756465206f72616c2073746174656d656e" +
"747320696e20494554462073657373696f6e732c2061732077656c6c20617320" +
"7772697474656e20616e6420656c656374726f6e696320636f6d6d756e696361" +
"74696f6e73206d61646520617420616e792074696d65206f7220706c6163652c" +
"207768696368206172652061646472657373656420746f",
null,
"a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d4b7955ec" +
"2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f56e031ca5eb6250d" +
"4042e02785ececfa4b4bb5e8ead0440e20b6e8db09d881a7c6132f420e527950" +
"42bdfa7773d8a9051447b3291ce1411c680465552aa6c405b7764d5e87bea85a" +
"d00f8449ed8f72d0d662ab052691ca66424bc86d2df80ea41f43abf937d3259d" +
"c4b2d0dfb48a6c9139ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b" +
"0871cdac638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6c" +
"cc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e818b04b0b" +
"c39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80ef2554d7189c411f" +
"5869ca52c5b83fa36ff216b9c1d30062bebcfd2dc5bce0911934fda79a86f6e6" +
"98ced759c3ff9b6477338f3da4f9cd8514ea9982ccafb341b2384dd902f3d1ab" +
"7ac61dd29c6f21ba5b862f3730e37cfdc4fd806c22f221"));
add(new TestData("RFC 7539 Test Vector 3",
"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
"000000000000000000000002",
42, Cipher.ENCRYPT_MODE,
"2754776173206272696c6c69672c20616e642074686520736c6974687920746f" +
"7665730a446964206779726520616e642067696d626c6520696e207468652077" +
"6162653a0a416c6c206d696d737920776572652074686520626f726f676f7665" +
"732c0a416e6420746865206d6f6d65207261746873206f757467726162652e",
null,
"62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf" +
"166d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f60553eb" +
"f39c6402c42234e32a356b3e764312a61a5532055716ead6962568f87d3f3f77" +
"04c6a8d1bcd1bf4d50d6154b6da731b187b58dfd728afa36757a797ac188d1"));
}};
public static final List<TestData> aeadTestList =
new LinkedList<TestData>() {{
add(new TestData("RFC 7539 Sample AEAD Test Vector",
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
"070000004041424344454647",
1, Cipher.ENCRYPT_MODE,
"4c616469657320616e642047656e746c656d656e206f662074686520636c6173" +
"73206f66202739393a204966204920636f756c64206f6666657220796f75206f" +
"6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" +
"637265656e20776f756c642062652069742e",
"50515253c0c1c2c3c4c5c6c7",
"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6" +
"3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36" +
"92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc" +
"3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd060" +
"0691"));
add(new TestData("RFC 7539 A.5 Sample Decryption",
"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
"000000000102030405060708",
1, Cipher.DECRYPT_MODE,
"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb2" +
"4c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf" +
"332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c855" +
"9797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4" +
"b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523e" +
"af4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a" +
"0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a10" +
"49e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29" +
"a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38",
"f33388860000000000004e91",
"496e7465726e65742d4472616674732061726520647261667420646f63756d65" +
"6e74732076616c696420666f722061206d6178696d756d206f6620736978206d" +
"6f6e74687320616e64206d617920626520757064617465642c207265706c6163" +
"65642c206f72206f62736f6c65746564206279206f7468657220646f63756d65" +
"6e747320617420616e792074696d652e20497420697320696e617070726f7072" +
"6961746520746f2075736520496e7465726e65742d4472616674732061732072" +
"65666572656e6365206d6174657269616c206f7220746f206369746520746865" +
"6d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67" +
"726573732e2fe2809d"));
}};
public static void main(String args[]) throws Exception {
int testsPassed = 0;
int testNumber = 0;
System.out.println("----- Single-part (byte[]) Tests -----");
for (TestData test : testList) {
System.out.println("*** Test " + ++testNumber + ": " +
test.testName);
if (runSinglePartTest(test)) {
testsPassed++;
}
}
System.out.println();
System.out.println("----- Single-part (ByteBuffer) Tests -----");
for (TestData test : testList) {
System.out.println("*** Test " + ++testNumber + ": " +
test.testName);
if (runByteBuffer(test)) {
testsPassed++;
}
}
System.out.println();
System.out.println("----- Multi-part Tests -----");
for (TestData test : testList) {
System.out.println("*** Test " + ++testNumber + ": " +
test.testName);
if (runMultiPartTest(test)) {
testsPassed++;
}
}
System.out.println();
System.out.println("----- AEAD Tests -----");
for (TestData test : aeadTestList) {
System.out.println("*** Test " + ++testNumber + ": " +
test.testName);
if (runAEADTest(test)) {
testsPassed++;
}
}
System.out.println();
System.out.println("Total tests: " + testNumber +
", Passed: " + testsPassed + ", Failed: " +
(testNumber - testsPassed));
if (testsPassed != testNumber) {
throw new RuntimeException("One or more tests failed. " +
"Check output for details");
}
}
private static boolean runSinglePartTest(TestData testData)
throws GeneralSecurityException {
boolean encRes = false;
boolean decRes = false;
byte[] encryptedResult;
byte[] decryptedResult;
// Get a Cipher instance and set up the parameters
Cipher mambo = Cipher.getInstance("ChaCha20");
SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20");
ChaCha20ParameterSpec mamboSpec = new ChaCha20ParameterSpec(
testData.nonce, testData.counter);
// Encrypt our input
mambo.init(Cipher.ENCRYPT_MODE, mamboKey, mamboSpec);
encryptedResult = mambo.doFinal(testData.input);
if (!Arrays.equals(encryptedResult, testData.expOutput)) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(testData.expOutput, 16, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(encryptedResult, 16, "\n", " "));
System.out.println();
} else {
encRes = true;
}
// Decrypt the result of the encryption operation
mambo = Cipher.getInstance("ChaCha20");
mambo.init(Cipher.DECRYPT_MODE, mamboKey, mamboSpec);
decryptedResult = mambo.doFinal(encryptedResult);
if (!Arrays.equals(decryptedResult, testData.input)) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(testData.input, 16, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(decryptedResult, 16, "\n", " "));
System.out.println();
} else {
decRes = true;
}
return (encRes && decRes);
}
private static boolean runMultiPartTest(TestData testData)
throws GeneralSecurityException {
boolean encRes = false;
boolean decRes = false;
// Get a cipher instance and initialize it
Cipher mambo = Cipher.getInstance("ChaCha20");
SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20");
ChaCha20ParameterSpec mamboSpec = new ChaCha20ParameterSpec(
testData.nonce, testData.counter);
byte[] encryptedResult = new byte[testData.input.length];
mambo.init(Cipher.ENCRYPT_MODE, mamboKey, mamboSpec);
System.out.print("Encrypt - ");
doMulti(mambo, testData.input, encryptedResult);
if (!Arrays.equals(encryptedResult, testData.expOutput)) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(testData.expOutput, 16, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(encryptedResult, 16, "\n", " "));
System.out.println();
} else {
encRes = true;
}
// Decrypt the result of the encryption operation
mambo = Cipher.getInstance("ChaCha20");
byte[] decryptedResult = new byte[encryptedResult.length];
mambo.init(Cipher.DECRYPT_MODE, mamboKey, mamboSpec);
System.out.print("Decrypt - ");
doMulti(mambo, encryptedResult, decryptedResult);
if (!Arrays.equals(decryptedResult, testData.input)) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(testData.input, 16, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(decryptedResult, 16, "\n", " "));
System.out.println();
} else {
decRes = true;
}
return (encRes && decRes);
}
private static void doMulti(Cipher c, byte[] input, byte[] output)
throws GeneralSecurityException {
int offset = 0;
boolean done = false;
Random randIn = new Random(System.currentTimeMillis());
// Send small updates between 1 - 8 bytes in length until we get
// 8 or less bytes from the end of the input, then finalize.
System.out.println("Input length: " + input.length);
System.out.print("Multipart (bytes in/out): ");
while (!done) {
int mPartLen = randIn.nextInt(8) + 1;
int bytesLeft = input.length - offset;
int processed;
if (mPartLen < bytesLeft) {
System.out.print(mPartLen + "/");
processed = c.update(input, offset, mPartLen,
output, offset);
offset += processed;
System.out.print(processed + " ");
} else {
processed = c.doFinal(input, offset, bytesLeft,
output, offset);
System.out.print(bytesLeft + "/" + processed + " ");
done = true;
}
}
System.out.println();
}
private static boolean runByteBuffer(TestData testData)
throws GeneralSecurityException {
boolean encRes = false;
boolean decRes = false;
// Get a cipher instance and initialize it
Cipher mambo = Cipher.getInstance("ChaCha20");
SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20");
ChaCha20ParameterSpec mamboSpec = new ChaCha20ParameterSpec(
testData.nonce, testData.counter);
mambo.init(Cipher.ENCRYPT_MODE, mamboKey, mamboSpec);
ByteBuffer bbIn = ByteBuffer.wrap(testData.input);
ByteBuffer bbEncOut = ByteBuffer.allocate(
mambo.getOutputSize(testData.input.length));
ByteBuffer bbExpOut = ByteBuffer.wrap(testData.expOutput);
mambo.doFinal(bbIn, bbEncOut);
bbIn.rewind();
bbEncOut.rewind();
if (bbEncOut.compareTo(bbExpOut) != 0) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(bbExpOut, 16, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(bbEncOut, 16, "\n", " "));
System.out.println();
} else {
encRes = true;
}
// Decrypt the result of the encryption operation
mambo = Cipher.getInstance("ChaCha20");
mambo.init(Cipher.DECRYPT_MODE, mamboKey, mamboSpec);
System.out.print("Decrypt - ");
ByteBuffer bbDecOut = ByteBuffer.allocate(
mambo.getOutputSize(bbEncOut.remaining()));
mambo.doFinal(bbEncOut, bbDecOut);
bbEncOut.rewind();
bbDecOut.rewind();
if (bbDecOut.compareTo(bbIn) != 0) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(bbIn, 16, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(bbDecOut, 16, "\n", " "));
System.out.println();
} else {
decRes = true;
}
return (encRes && decRes);
}
private static boolean runAEADTest(TestData testData)
throws GeneralSecurityException {
boolean result = false;
Cipher mambo = Cipher.getInstance("ChaCha20-Poly1305");
SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20");
IvParameterSpec mamboSpec = new IvParameterSpec(testData.nonce);
mambo.init(testData.direction, mamboKey, mamboSpec);
byte[] out = new byte[mambo.getOutputSize(testData.input.length)];
int outOff = 0;
try {
mambo.updateAAD(testData.aad);
outOff += mambo.update(testData.input, 0, testData.input.length,
out, outOff);
outOff += mambo.doFinal(out, outOff);
} catch (AEADBadTagException abte) {
// If we get a bad tag or derive a tag mismatch, log it
// and register it as a failure
System.out.println("FAIL: " + abte);
return false;
}
if (!Arrays.equals(out, testData.expOutput)) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(testData.expOutput, 16, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(out, 16, "\n", " "));
System.out.println();
} else {
result = true;
}
return result;
}
/**
* Dump the hex bytes of a buffer into string form.
*
* @param data The array of bytes to dump to stdout.
* @param itemsPerLine The number of bytes to display per line
* if the {@code lineDelim} character is blank then all bytes
* will be printed on a single line.
* @param lineDelim The delimiter between lines
* @param itemDelim The delimiter between bytes
*
* @return The hexdump of the byte array
*/
private static String dumpHexBytes(byte[] data, int itemsPerLine,
String lineDelim, String itemDelim) {
return dumpHexBytes(ByteBuffer.wrap(data), itemsPerLine, lineDelim,
itemDelim);
}
private static String dumpHexBytes(ByteBuffer data, int itemsPerLine,
String lineDelim, String itemDelim) {
StringBuilder sb = new StringBuilder();
if (data != null) {
data.mark();
int i = 0;
while (data.remaining() > 0) {
if (i % itemsPerLine == 0 && i != 0) {
sb.append(lineDelim);
}
sb.append(String.format("%02X", data.get())).append(itemDelim);
i++;
}
data.reset();
}
return sb.toString();
}
}

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2018, 2021, 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.
*
* 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.
*/
/*
* @test
* @bug 8153029
* @summary ChaCha20 key generator test.
* @library /test/lib
*/
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.util.HexFormat;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.ChaCha20ParameterSpec;
public class ChaCha20KeyGeneratorTest {
public static void main(String[] args) throws Exception {
KeyGenerator generator = KeyGenerator.getInstance("ChaCha20");
try {
generator.init(new ChaCha20ParameterSpec(
HexFormat.of().parseHex("100000000000000000000000"), 0));
throw new RuntimeException(
"ChaCha20 key generation should not consume AlgorithmParameterSpec");
} catch (InvalidAlgorithmParameterException e) {
System.out.println("Expected InvalidAlgorithmParameterException: "
+ e.getMessage());
}
for (int keySize : new int[] { 32, 64, 128, 512, 1024 }) {
try {
generator.init(keySize);
throw new RuntimeException("The key size for ChaCha20 must be 256");
} catch (InvalidParameterException e) {
System.out.println(
"Expected InvalidParameterException: " + keySize);
}
}
generator.init(256);
SecretKey key = generator.generateKey();
byte[] keyValue = key.getEncoded();
System.out.println("Key: " + HexFormat.of().formatHex(keyValue));
if (keyValue.length != 32) {
throw new RuntimeException("The size of generated key must be 256");
}
}
}

View file

@ -0,0 +1,614 @@
/*
* Copyright (c) 2018, 2023, 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.
*
* 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.
*/
/**
* @test
* @bug 8153029 8305091
* @library /test/lib
* @run main ChaCha20NoReuse
* @summary ChaCha20 Cipher Implementation (key/nonce reuse protection)
*/
import java.util.*;
import javax.crypto.Cipher;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.ChaCha20ParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.AEADBadTagException;
import javax.crypto.SecretKey;
import java.security.InvalidKeyException;
public class ChaCha20NoReuse {
private static final String ALG_CC20 = "ChaCha20";
private static final String ALG_CC20_P1305 = "ChaCha20-Poly1305";
/**
* Basic TestMethod interface definition.
*/
public interface TestMethod {
/**
* Runs the actual test case
*
* @param algorithm the algorithm to use (e.g. ChaCha20, etc.)
*
* @return true if the test passes, false otherwise.
*/
boolean run(String algorithm);
/**
* Check if this TestMethod can be run for this algorithm. Some tests
* are specific to ChaCha20 or ChaCha20-Poly1305, so this method
* can be used to determine if a given Cipher type is appropriate.
*
* @param algorithm the algorithm to use.
*
* @return true if this test can be run on this algorithm,
* false otherwise.
*/
boolean isValid(String algorithm);
}
public static class TestData {
public TestData(String name, String keyStr, String nonceStr, int ctr,
int dir, String inputStr, String aadStr, String outStr) {
testName = Objects.requireNonNull(name);
HexFormat hex = HexFormat.of();
key = hex.parseHex(keyStr);
nonce = hex.parseHex(nonceStr);
if ((counter = ctr) < 0) {
throw new IllegalArgumentException(
"counter must be 0 or greater");
}
direction = dir;
if ((direction != Cipher.ENCRYPT_MODE) &&
(direction != Cipher.DECRYPT_MODE)) {
throw new IllegalArgumentException(
"Direction must be ENCRYPT_MODE or DECRYPT_MODE");
}
input = hex.parseHex(inputStr);
aad = (aadStr != null) ? hex.parseHex(aadStr) : null;
expOutput = hex.parseHex(outStr);
}
public final String testName;
public final byte[] key;
public final byte[] nonce;
public final int counter;
public final int direction;
public final byte[] input;
public final byte[] aad;
public final byte[] expOutput;
}
public static final List<TestData> testList = new LinkedList<TestData>() {{
add(new TestData("RFC 7539 Sample Test Vector [ENCRYPT]",
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"000000000000004a00000000",
1, Cipher.ENCRYPT_MODE,
"4c616469657320616e642047656e746c656d656e206f662074686520636c6173" +
"73206f66202739393a204966204920636f756c64206f6666657220796f75206f" +
"6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" +
"637265656e20776f756c642062652069742e",
null,
"6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0b" +
"f91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d8" +
"07ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab7793736" +
"5af90bbf74a35be6b40b8eedf2785e42874d"));
add(new TestData("RFC 7539 Sample Test Vector [DECRYPT]",
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"000000000000004a00000000",
1, Cipher.DECRYPT_MODE,
"6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0b" +
"f91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d8" +
"07ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab7793736" +
"5af90bbf74a35be6b40b8eedf2785e42874d",
null,
"4c616469657320616e642047656e746c656d656e206f662074686520636c6173" +
"73206f66202739393a204966204920636f756c64206f6666657220796f75206f" +
"6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" +
"637265656e20776f756c642062652069742e"));
}};
public static final List<TestData> aeadTestList =
new LinkedList<TestData>() {{
add(new TestData("RFC 7539 Sample AEAD Test Vector",
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
"070000004041424344454647",
1, Cipher.ENCRYPT_MODE,
"4c616469657320616e642047656e746c656d656e206f662074686520636c6173" +
"73206f66202739393a204966204920636f756c64206f6666657220796f75206f" +
"6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" +
"637265656e20776f756c642062652069742e",
"50515253c0c1c2c3c4c5c6c7",
"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6" +
"3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36" +
"92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc" +
"3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd060" +
"0691"));
add(new TestData("RFC 7539 A.5 Sample Decryption",
"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
"000000000102030405060708",
1, Cipher.DECRYPT_MODE,
"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb2" +
"4c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf" +
"332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c855" +
"9797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4" +
"b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523e" +
"af4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a" +
"0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a10" +
"49e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29" +
"a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38",
"f33388860000000000004e91",
"496e7465726e65742d4472616674732061726520647261667420646f63756d65" +
"6e74732076616c696420666f722061206d6178696d756d206f6620736978206d" +
"6f6e74687320616e64206d617920626520757064617465642c207265706c6163" +
"65642c206f72206f62736f6c65746564206279206f7468657220646f63756d65" +
"6e747320617420616e792074696d652e20497420697320696e617070726f7072" +
"6961746520746f2075736520496e7465726e65742d4472616674732061732072" +
"65666572656e6365206d6174657269616c206f7220746f206369746520746865" +
"6d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67" +
"726573732e2fe2809d"));
}};
/**
* Make sure we do not use this Cipher object without initializing it
* at all
*/
public static final TestMethod noInitTest = new TestMethod() {
@Override
public boolean isValid(String algorithm) {
return true; // Valid for all algs
}
@Override
public boolean run(String algorithm) {
System.out.println("----- No Init Test [" + algorithm +
"] -----");
try {
Cipher cipher = Cipher.getInstance(algorithm);
TestData testData;
switch (algorithm) {
case ALG_CC20:
testData = testList.get(0);
break;
case ALG_CC20_P1305:
testData = aeadTestList.get(0);
break;
default:
throw new IllegalArgumentException(
"Unsupported cipher type: " + algorithm);
}
// Attempting to use the cipher without initializing it
// should throw an IllegalStateException
try {
if (algorithm.equals(ALG_CC20_P1305)) {
cipher.updateAAD(testData.aad);
}
cipher.doFinal(testData.input);
throw new RuntimeException(
"Expected IllegalStateException not thrown");
} catch (IllegalStateException ise) {
// Do nothing, this is what we expected to happen
}
} catch (Exception exc) {
System.out.println("Unexpected exception: " + exc);
exc.printStackTrace();
return false;
}
return true;
}
};
/**
* Make sure we don't allow a double init using the same parameters
*/
public static final TestMethod doubleInitTest = new TestMethod() {
@Override
public boolean isValid(String algorithm) {
return true; // Valid for all algs
}
@Override
public boolean run(String algorithm) {
System.out.println("----- Double Init Test [" + algorithm +
"] -----");
try {
AlgorithmParameterSpec spec;
Cipher cipher = Cipher.getInstance(algorithm);
TestData testData;
switch (algorithm) {
case ALG_CC20:
testData = testList.get(0);
spec = new ChaCha20ParameterSpec(testData.nonce,
testData.counter);
break;
case ALG_CC20_P1305:
testData = aeadTestList.get(0);
spec = new IvParameterSpec(testData.nonce);
break;
default:
throw new IllegalArgumentException(
"Unsupported cipher type: " + algorithm);
}
SecretKey key = new SecretKeySpec(testData.key, ALG_CC20);
// Initialize the first time, this should work.
cipher.init(testData.direction, key, spec);
// Immediately initializing a second time with the same
// parameters should fail
try {
cipher.init(testData.direction, key, spec);
throw new RuntimeException(
"Expected InvalidKeyException not thrown");
} catch (InvalidKeyException ike) {
// Do nothing, this is what we expected to happen
}
} catch (Exception exc) {
System.out.println("Unexpected exception: " + exc);
exc.printStackTrace();
return false;
}
return true;
}
};
/**
* Attempt to run two full encryption operations without an init in
* between.
*/
public static final TestMethod encTwiceNoInit = new TestMethod() {
@Override
public boolean isValid(String algorithm) {
return true; // Valid for all algs
}
@Override
public boolean run(String algorithm) {
System.out.println("----- Encrypt second time without init [" +
algorithm + "] -----");
try {
AlgorithmParameterSpec spec;
Cipher cipher = Cipher.getInstance(algorithm);
TestData testData;
switch (algorithm) {
case ALG_CC20:
testData = testList.get(0);
spec = new ChaCha20ParameterSpec(testData.nonce,
testData.counter);
break;
case ALG_CC20_P1305:
testData = aeadTestList.get(0);
spec = new IvParameterSpec(testData.nonce);
break;
default:
throw new IllegalArgumentException(
"Unsupported cipher type: " + algorithm);
}
SecretKey key = new SecretKeySpec(testData.key, ALG_CC20);
// Initialize and encrypt
cipher.init(testData.direction, key, spec);
if (algorithm.equals(ALG_CC20_P1305)) {
cipher.updateAAD(testData.aad);
}
cipher.doFinal(testData.input);
System.out.println("First encryption complete");
// Now attempt to encrypt again without changing the key/IV
// This should fail.
try {
if (algorithm.equals(ALG_CC20_P1305)) {
cipher.updateAAD(testData.aad);
}
cipher.doFinal(testData.input);
throw new RuntimeException(
"Expected IllegalStateException not thrown");
} catch (IllegalStateException ise) {
// Do nothing, this is what we expected to happen
}
} catch (Exception exc) {
System.out.println("Unexpected exception: " + exc);
exc.printStackTrace();
return false;
}
return true;
}
};
/**
* Attempt to run two full decryption operations without an init in
* between.
*/
public static final TestMethod decTwiceNoInit = new TestMethod() {
@Override
public boolean isValid(String algorithm) {
return true; // Valid for all algs
}
@Override
public boolean run(String algorithm) {
System.out.println("----- Decrypt second time without init [" +
algorithm + "] -----");
try {
AlgorithmParameterSpec spec;
Cipher cipher = Cipher.getInstance(algorithm);
TestData testData;
switch (algorithm) {
case ALG_CC20:
testData = testList.get(1);
spec = new ChaCha20ParameterSpec(testData.nonce,
testData.counter);
break;
case ALG_CC20_P1305:
testData = aeadTestList.get(1);
spec = new IvParameterSpec(testData.nonce);
break;
default:
throw new IllegalArgumentException(
"Unsupported cipher type: " + algorithm);
}
SecretKey key = new SecretKeySpec(testData.key, ALG_CC20);
// Initialize and decrypt
cipher.init(testData.direction, key, spec);
if (algorithm.equals(ALG_CC20_P1305)) {
cipher.updateAAD(testData.aad);
}
cipher.doFinal(testData.input);
System.out.println("First decryption complete");
// Now attempt to decrypt again without changing the key/IV
// We allow this scenario.
if (algorithm.equals(ALG_CC20_P1305)) {
cipher.updateAAD(testData.aad);
}
cipher.doFinal(testData.input);
} catch (Exception exc) {
System.out.println("Unexpected exception: " + exc);
exc.printStackTrace();
return false;
}
return true;
}
};
/**
* Perform an AEAD decryption with corrupted data so the tag does not
* match. Then use the uncorrupted test vector input and attempt to
* reuse the cipher without initialization.
*/
public static final TestMethod decFailNoInit = new TestMethod() {
@Override
public boolean isValid(String algorithm) {
return algorithm.equals(ALG_CC20_P1305);
}
@Override
public boolean run(String algorithm) {
System.out.println(
"----- Fail decryption, try again with no init [" +
algorithm + "] -----");
try {
TestData testData = aeadTestList.get(1);
AlgorithmParameterSpec spec =
new IvParameterSpec(testData.nonce);
byte[] corruptInput = testData.input.clone();
corruptInput[0]++; // Corrupt the ciphertext
SecretKey key = new SecretKeySpec(testData.key, ALG_CC20);
Cipher cipher = Cipher.getInstance(algorithm);
try {
// Initialize and encrypt
cipher.init(testData.direction, key, spec);
cipher.updateAAD(testData.aad);
cipher.doFinal(corruptInput);
throw new RuntimeException(
"Expected AEADBadTagException not thrown");
} catch (AEADBadTagException abte) {
System.out.println("Expected decryption failure occurred");
}
// Even though an exception occurred during decryption, the
// Cipher object should be returned to its post-init state.
// Since this is a decryption operation, we should allow
// key/nonce reuse. It should properly decrypt the uncorrupted
// input.
cipher.updateAAD(testData.aad);
byte[] pText = cipher.doFinal(testData.input);
if (!Arrays.equals(pText, testData.expOutput)) {
throw new RuntimeException("FAIL: Attempted decryption " +
"did not match expected plaintext");
}
} catch (Exception exc) {
System.out.println("Unexpected exception: " + exc);
exc.printStackTrace();
return false;
}
return true;
}
};
/**
* Encrypt once successfully, then attempt to init with the same
* key and nonce.
*/
public static final TestMethod encTwiceInitSameParams = new TestMethod() {
@Override
public boolean isValid(String algorithm) {
return true; // Valid for all algs
}
@Override
public boolean run(String algorithm) {
System.out.println("----- Encrypt, then init with same params [" +
algorithm + "] -----");
try {
AlgorithmParameterSpec spec;
Cipher cipher = Cipher.getInstance(algorithm);
TestData testData;
switch (algorithm) {
case ALG_CC20:
testData = testList.get(0);
spec = new ChaCha20ParameterSpec(testData.nonce,
testData.counter);
break;
case ALG_CC20_P1305:
testData = aeadTestList.get(0);
spec = new IvParameterSpec(testData.nonce);
break;
default:
throw new IllegalArgumentException(
"Unsupported cipher type: " + algorithm);
}
SecretKey key = new SecretKeySpec(testData.key, ALG_CC20);
// Initialize then encrypt
cipher.init(testData.direction, key, spec);
if (algorithm.equals(ALG_CC20_P1305)) {
cipher.updateAAD(testData.aad);
}
cipher.doFinal(testData.input);
System.out.println("First encryption complete");
// Initializing after the completed encryption with
// the same key and nonce should fail.
try {
cipher.init(testData.direction, key, spec);
throw new RuntimeException(
"Expected InvalidKeyException not thrown");
} catch (InvalidKeyException ike) {
// Do nothing, this is what we expected to happen
}
} catch (Exception exc) {
System.out.println("Unexpected exception: " + exc);
exc.printStackTrace();
return false;
}
return true;
}
};
/**
* Decrypt once successfully, then attempt to init with the same
* key and nonce.
*/
public static final TestMethod decTwiceInitSameParams = new TestMethod() {
@Override
public boolean isValid(String algorithm) {
return true; // Valid for all algs
}
@Override
public boolean run(String algorithm) {
System.out.println("----- Decrypt, then init with same params [" +
algorithm + "] -----");
try {
AlgorithmParameterSpec spec;
Cipher cipher = Cipher.getInstance(algorithm);
TestData testData;
switch (algorithm) {
case ALG_CC20:
testData = testList.get(1);
spec = new ChaCha20ParameterSpec(testData.nonce,
testData.counter);
break;
case ALG_CC20_P1305:
testData = aeadTestList.get(1);
spec = new IvParameterSpec(testData.nonce);
break;
default:
throw new IllegalArgumentException(
"Unsupported cipher type: " + algorithm);
}
SecretKey key = new SecretKeySpec(testData.key, ALG_CC20);
// Initialize then decrypt
cipher.init(testData.direction, key, spec);
if (algorithm.equals(ALG_CC20_P1305)) {
cipher.updateAAD(testData.aad);
}
byte[] pText = cipher.doFinal(testData.input);
if (!Arrays.equals(pText, testData.expOutput)) {
throw new RuntimeException("FAIL: Attempted decryption " +
"did not match expected plaintext");
}
System.out.println("First decryption complete");
// Initializing after the completed decryption with
// the same key and nonce is allowed.
cipher.init(testData.direction, key, spec);
System.out.println("Successful reinit in DECRYPT_MODE");
} catch (Exception exc) {
System.out.println("Unexpected exception: " + exc);
exc.printStackTrace();
return false;
}
return true;
}
};
public static final List<String> algList =
Arrays.asList(ALG_CC20, ALG_CC20_P1305);
public static final List<TestMethod> testMethodList =
Arrays.asList(noInitTest, doubleInitTest, encTwiceNoInit,
decTwiceNoInit, decFailNoInit, encTwiceInitSameParams,
decTwiceInitSameParams);
public static void main(String args[]) throws Exception {
int testsPassed = 0;
int testNumber = 0;
for (TestMethod tm : testMethodList) {
for (String alg : algList) {
if (tm.isValid(alg)) {
testNumber++;
boolean result = tm.run(alg);
System.out.println("Result: " + (result ? "PASS" : "FAIL"));
if (result) {
testsPassed++;
}
}
}
}
System.out.println("Total Tests: " + testNumber +
", Tests passed: " + testsPassed);
if (testsPassed < testNumber) {
throw new RuntimeException(
"Not all tests passed. See output for failure info");
}
}
}

View file

@ -0,0 +1,524 @@
/*
* Copyright (c) 2018, 2021, 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.
*
* 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.
*/
/**
* @test
* @bug 8153029 8257769
* @library /test/lib
* @run main ChaCha20Poly1305ParamTest
* @summary ChaCha20 Cipher Implementation (parameters)
*/
import java.util.*;
import java.io.IOException;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.ChaCha20ParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.AEADBadTagException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.IvParameterSpec;
import jdk.test.lib.Convert;
public class ChaCha20Poly1305ParamTest {
public static class TestData {
public TestData(String name, String keyStr, String nonceStr, int ctr,
int dir, String inputStr, String aadStr, String outStr) {
testName = Objects.requireNonNull(name);
HexFormat hex = HexFormat.of();
key = hex.parseHex(keyStr);
nonce = hex.parseHex(nonceStr);
if ((counter = ctr) < 0) {
throw new IllegalArgumentException(
"counter must be 0 or greater");
}
direction = dir;
if ((direction != Cipher.ENCRYPT_MODE) &&
(direction != Cipher.DECRYPT_MODE)) {
throw new IllegalArgumentException(
"Direction must be ENCRYPT_MODE or DECRYPT_MODE");
}
input = hex.parseHex(inputStr);
aad = (aadStr != null) ? hex.parseHex(aadStr) : null;
expOutput = hex.parseHex(outStr);
}
public final String testName;
public final byte[] key;
public final byte[] nonce;
public final int counter;
public final int direction;
public final byte[] input;
public final byte[] aad;
public final byte[] expOutput;
}
public static final List<TestData> aeadTestList =
new LinkedList<TestData>() {{
add(new TestData("RFC 7539 Sample AEAD Test Vector",
"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
"070000004041424344454647",
1, Cipher.ENCRYPT_MODE,
"4c616469657320616e642047656e746c656d656e206f662074686520636c6173" +
"73206f66202739393a204966204920636f756c64206f6666657220796f75206f" +
"6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73" +
"637265656e20776f756c642062652069742e",
"50515253c0c1c2c3c4c5c6c7",
"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d6" +
"3dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b36" +
"92ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc" +
"3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd060" +
"0691"));
add(new TestData("RFC 7539 A.5 Sample Decryption",
"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
"000000000102030405060708",
1, Cipher.DECRYPT_MODE,
"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb2" +
"4c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf" +
"332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c855" +
"9797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4" +
"b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523e" +
"af4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a" +
"0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a10" +
"49e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29" +
"a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38",
"f33388860000000000004e91",
"496e7465726e65742d4472616674732061726520647261667420646f63756d65" +
"6e74732076616c696420666f722061206d6178696d756d206f6620736978206d" +
"6f6e74687320616e64206d617920626520757064617465642c207265706c6163" +
"65642c206f72206f62736f6c65746564206279206f7468657220646f63756d65" +
"6e747320617420616e792074696d652e20497420697320696e617070726f7072" +
"6961746520746f2075736520496e7465726e65742d4472616674732061732072" +
"65666572656e6365206d6174657269616c206f7220746f206369746520746865" +
"6d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67" +
"726573732e2fe2809d"));
}};
// 12-byte nonce DER-encoded as an OCTET_STRING
public static final byte[] NONCE_OCTET_STR_12 = {
4, 12, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8
};
// Invalid 16-byte nonce DER-encoded as an OCTET_STRING
public static final byte[] NONCE_OCTET_STR_16 = {
4, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
// Throwaway key for default init tests
public static final SecretKey DEF_KEY = new SecretKeySpec(new byte[]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
}, "ChaCha20");
public static void main(String args[]) throws Exception {
int testsPassed = 0;
int testNumber = 0;
// Try some default initializations
testDefaultAlgParams("ChaCha20", Cipher.ENCRYPT_MODE, true);
testDefaultAlgParams("ChaCha20-Poly1305", Cipher.ENCRYPT_MODE, true);
testDefaultAlgParamSpec("ChaCha20", Cipher.ENCRYPT_MODE, true);
testDefaultAlgParamSpec("ChaCha20-Poly1305", Cipher.ENCRYPT_MODE, true);
testDefaultAlgParams("ChaCha20", Cipher.DECRYPT_MODE, false);
testDefaultAlgParams("ChaCha20-Poly1305", Cipher.DECRYPT_MODE, false);
testDefaultAlgParamSpec("ChaCha20", Cipher.DECRYPT_MODE, false);
testDefaultAlgParamSpec("ChaCha20-Poly1305", Cipher.DECRYPT_MODE,
false);
// Try (and hopefully fail) to create a ChaCha20 AlgorithmParameterSpec
System.out.println(
"*** Test: Try to make ChaCha20 AlgorithmParameterSpec");
try {
ChaCha20ParameterSpec badChaCha20Spec =
new ChaCha20ParameterSpec(NONCE_OCTET_STR_16, 1);
throw new RuntimeException("ChaCha20 AlgorithmParameterSpec " +
"with 16 byte nonce should fail");
} catch (IllegalArgumentException iae) {
System.out.println("Caught expected exception: " + iae);
}
// Try (and hopefully fail) to create a ChaCha20 AlgorithmParameters
System.out.println(
"*** Test: Try to make ChaCha20 AlgorithmParameters");
try {
AlgorithmParameters apsNoChaCha20 =
AlgorithmParameters.getInstance("ChaCha20");
throw new RuntimeException(
"ChaCha20 AlgorithmParameters should fail");
} catch (NoSuchAlgorithmException nsae) {
System.out.println("Caught expected exception: " + nsae);
}
// Create the AlgorithmParameters object from a valid encoding
System.out.println("*** Test: Create and init ChaCha20-Poly1305 APS");
AlgorithmParameters apsGood =
AlgorithmParameters.getInstance("ChaCha20-Poly1305");
apsGood.init(NONCE_OCTET_STR_12);
System.out.println("Test Passed");
// Pull an AlgorithmParameters object out of the initialized cipher
// and compare its value against the original.
System.out.println("*** Test: Init ChaCha20-Poly1305 Cipher using " +
"AP, retrieve AP and compare");
Cipher cc20p1305 = Cipher.getInstance("ChaCha20-Poly1305");
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY, apsGood);
AlgorithmParameters pulledParams = cc20p1305.getParameters();
byte[] apsGoodData = apsGood.getEncoded();
byte[] pulledParamsData = pulledParams.getEncoded();
if (!Arrays.equals(apsGoodData, pulledParamsData)) {
throw new RuntimeException(
"Retrieved parameters do not match those used to init cipher");
}
System.out.println("Test Passed");
// Try the same test with ChaCha20. It should always be null.
System.out.println("*** Test: Init ChaCha20 Cipher using " +
"AP, retrieve AP and compare");
Cipher cc20 = Cipher.getInstance("ChaCha20");
cc20.init(Cipher.ENCRYPT_MODE, DEF_KEY);
pulledParams = cc20.getParameters();
if (pulledParams != null) {
throw new RuntimeException("Unexpected non-null " +
"AlgorithmParameters from ChaCha20 cipiher");
}
System.out.println("Test Passed");
// Create and try to init using invalid encoding
AlgorithmParameters apsBad =
AlgorithmParameters.getInstance("ChaCha20-Poly1305");
System.out.println("*** Test: Use invalid encoding scheme");
try {
apsBad.init(NONCE_OCTET_STR_12, "OraclePrivate");
throw new RuntimeException("Allowed unsupported encoding scheme: " +
apsBad.getAlgorithm());
} catch (IOException iae) {
System.out.println("Caught expected exception: " + iae);
}
// Try to init using supported scheme but invalid length
System.out.println("*** Test: Use supported scheme, nonce too large");
try {
apsBad.init(NONCE_OCTET_STR_16, "ASN.1");
throw new RuntimeException("Allowed invalid encoded length");
} catch (IOException ioe) {
System.out.println("Caught expected exception: " + ioe);
}
// The next set of tests cover cases where ChaCha20-Poly1305 cipher
// objects have the getParameters() call executed after instantiation
// but before initialization.
System.out.println("*** Test: getParameters before init");
cc20p1305 = Cipher.getInstance("ChaCha20-Poly1305");
AlgorithmParameters algParams = cc20p1305.getParameters();
byte[] preInitNonce = getNonceFromParams(algParams);
// A second pre-init getParameters() call should return a new set of
// random parameters.
AlgorithmParameters algParamsTwo = cc20p1305.getParameters();
byte[] secondNonce = getNonceFromParams(algParamsTwo);
if (MessageDigest.isEqual(preInitNonce, secondNonce)) {
throw new RuntimeException("Unexpected nonce match between " +
"two pre-init getParameters() calls");
}
// Next we will initialize the Cipher object using a form of init
// that doesn't take AlgorithmParameters or AlgorithmParameterSpec.
// The nonce created using the pre-init getParameters() call should
// be overwritten by a freshly generated set of random parameters.
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY);
AlgorithmParameters postInitAps = cc20p1305.getParameters();
byte[] postInitNonce = getNonceFromParams(postInitAps);
if (MessageDigest.isEqual(preInitNonce, postInitNonce)) {
throw new RuntimeException("Unexpected nonce match between " +
"pre and post-init getParameters() calls");
}
System.out.println("Test Passed");
// After an initialization, subsequent calls to getParameters() should
// return the same parameter value until the next initialization takes
// place.
System.out.println("*** Test: getParameters after init");
AlgorithmParameters postInitApsTwo = cc20p1305.getParameters();
byte[] postInitNonceTwo = getNonceFromParams(postInitApsTwo);
if (!MessageDigest.isEqual(postInitNonce, postInitNonceTwo)) {
throw new RuntimeException("Unexpected nonce mismatch between " +
"two post-init getParameters() calls");
}
System.out.println("Test Passed");
// Test reinitialization use cases.
// First test: instantiate, init(no param), encrypt. Get params
// and attempt to reinit with same parameters. Should fail.
System.out.println("*** Test: Init w/ random nonce, init 2nd time");
cc20p1305 = Cipher.getInstance("ChaCha20-Poly1305");
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY);
algParams = cc20p1305.getParameters();
preInitNonce = getNonceFromParams(algParams);
// Perform a simple encryption operation
cc20p1305.doFinal(aeadTestList.get(0).input);
try {
// Now try to reinitialize using the same parameters
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY, algParams);
throw new RuntimeException("Illegal key/nonce reuse");
} catch (InvalidKeyException ike) {
System.out.println("Caught expected exception: " + ike);
}
// Test the reinit guard using an AlgorithmParameterSpec with the
// Same nonce value. This should also be a failure.
try {
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY,
new IvParameterSpec(preInitNonce));
throw new RuntimeException("Illegal key/nonce reuse");
} catch (InvalidKeyException ike) {
System.out.println("Caught expected exception: " + ike);
}
// Try one more time, this time providing a new 12-byte nonce, which
// should be allowed even if the key is the same.
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY,
new IvParameterSpec(NONCE_OCTET_STR_12, 2, 12));
System.out.println("Test Passed");
// Reinit test: instantiate, init(no param), getParam, encrypt,
// then init(no param). Should work and the parameters should be
// different after each init.
cc20p1305 = Cipher.getInstance("ChaCha20-Poly1305");
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY);
byte[] paramInitOne = getNonceFromParams(cc20p1305.getParameters());
// Perform a simple encryption operation
cc20p1305.doFinal(aeadTestList.get(0).input);
// reinit (no params)
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY);
byte[] paramInitTwo = getNonceFromParams(cc20p1305.getParameters());
if (MessageDigest.isEqual(paramInitOne, paramInitTwo)) {
throw new RuntimeException("Unexpected nonce match between " +
"pre and post-init getParameters() calls");
}
System.out.println("Test Passed");
// Reinit test: instantiate, init(no param), doFinal, then doFinal
// again without intervening init. Should fail due to no-reuse
// protections.
try {
cc20p1305 = Cipher.getInstance("ChaCha20-Poly1305");
cc20p1305.init(Cipher.ENCRYPT_MODE, DEF_KEY);
cc20p1305.doFinal(aeadTestList.get(0).input);
cc20p1305.doFinal(aeadTestList.get(0).input);
throw new RuntimeException("Illegal key/nonce reuse");
} catch (IllegalStateException ise) {
System.out.println("Caught expected exception: " + ise);
}
System.out.println("----- AEAD Tests -----");
for (TestData test : aeadTestList) {
System.out.println("*** Test " + ++testNumber + ": " +
test.testName);
if (runAEADTest(test)) {
testsPassed++;
}
}
System.out.println();
System.out.println("Total tests: " + testNumber +
", Passed: " + testsPassed + ", Failed: " +
(testNumber - testsPassed));
if (testsPassed != testNumber) {
throw new RuntimeException("One or more tests failed. " +
"Check output for details");
}
}
/**
* Attempt default inits with null AlgorithmParameters
*
* @param alg the algorithm (ChaCha20, ChaCha20-Poly1305)
* @param mode the Cipher mode (ENCRYPT_MODE, etc.)
*/
private static void testDefaultAlgParams(String alg, int mode,
boolean shouldPass) {
byte[] ivOne = null, ivTwo = null;
System.out.println("Test default AlgorithmParameters: Cipher = " +
alg + ", mode = " + mode);
try {
AlgorithmParameters params = null;
Cipher cipher = Cipher.getInstance(alg);
cipher.init(mode, DEF_KEY, params, null);
ivOne = cipher.getIV();
cipher.init(mode, DEF_KEY, params, null);
ivTwo = cipher.getIV();
if (!shouldPass) {
throw new RuntimeException(
"Did not receive expected exception");
}
} catch (GeneralSecurityException gse) {
if (shouldPass) {
throw new RuntimeException(gse);
}
System.out.println("Caught expected exception: " + gse);
return;
}
if (Arrays.equals(ivOne, ivTwo)) {
throw new RuntimeException(
"FAIL! Two inits generated same nonces");
} else {
System.out.println("IV 1:\n" + dumpHexBytes(ivOne, 16, "\n", " "));
System.out.println("IV 1:\n" + dumpHexBytes(ivTwo, 16, "\n", " "));
}
}
/**
* Attempt default inits with null AlgorithmParameters
*
* @param alg the algorithm (ChaCha20, ChaCha20-Poly1305)
* @param mode the Cipher mode (ENCRYPT_MODE, etc.)
*/
private static void testDefaultAlgParamSpec(String alg, int mode,
boolean shouldPass) {
byte[] ivOne = null, ivTwo = null;
System.out.println("Test default AlgorithmParameterSpec: Cipher = " +
alg + ", mode = " + mode);
try {
AlgorithmParameterSpec params = null;
Cipher cipher = Cipher.getInstance(alg);
cipher.init(mode, DEF_KEY, params, null);
ivOne = cipher.getIV();
cipher.init(mode, DEF_KEY, params, null);
ivTwo = cipher.getIV();
if (!shouldPass) {
throw new RuntimeException(
"Did not receive expected exception");
}
} catch (GeneralSecurityException gse) {
if (shouldPass) {
throw new RuntimeException(gse);
}
System.out.println("Caught expected exception: " + gse);
return;
}
if (Arrays.equals(ivOne, ivTwo)) {
throw new RuntimeException(
"FAIL! Two inits generated same nonces");
} else {
System.out.println("IV 1:\n" + dumpHexBytes(ivOne, 16, "\n", " "));
System.out.println("IV 2:\n" + dumpHexBytes(ivTwo, 16, "\n", " "));
}
}
private static boolean runAEADTest(TestData testData)
throws GeneralSecurityException, IOException {
boolean result = false;
Cipher mambo = Cipher.getInstance("ChaCha20-Poly1305");
SecretKeySpec mamboKey = new SecretKeySpec(testData.key, "ChaCha20");
AlgorithmParameters mamboParams =
AlgorithmParameters.getInstance("ChaCha20-Poly1305");
// Put the nonce into ASN.1 ChaCha20-Poly1305 parameter format
byte[] derNonce = new byte[testData.nonce.length + 2];
derNonce[0] = 0x04;
derNonce[1] = (byte)testData.nonce.length;
System.arraycopy(testData.nonce, 0, derNonce, 2,
testData.nonce.length);
mamboParams.init(derNonce);
mambo.init(testData.direction, mamboKey, mamboParams);
byte[] out = new byte[mambo.getOutputSize(testData.input.length)];
int outOff = 0;
try {
mambo.updateAAD(testData.aad);
outOff += mambo.update(testData.input, 0, testData.input.length,
out, outOff);
outOff += mambo.doFinal(out, outOff);
} catch (AEADBadTagException abte) {
// If we get a bad tag or derive a tag mismatch, log it
// and register it as a failure
System.out.println("FAIL: " + abte);
return false;
}
if (!Arrays.equals(out, testData.expOutput)) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(testData.expOutput, 16, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(out, 16, "\n", " "));
System.out.println();
} else {
result = true;
}
return result;
}
private static byte[] getNonceFromParams(AlgorithmParameters params)
throws InvalidParameterSpecException {
return params.getParameterSpec(IvParameterSpec.class).getIV();
}
/**
* Dump the hex bytes of a buffer into string form.
*
* @param data The array of bytes to dump to stdout.
* @param itemsPerLine The number of bytes to display per line
* if the {@code lineDelim} character is blank then all bytes
* will be printed on a single line.
* @param lineDelim The delimiter between lines
* @param itemDelim The delimiter between bytes
*
* @return The hexdump of the byte array
*/
private static String dumpHexBytes(byte[] data, int itemsPerLine,
String lineDelim, String itemDelim) {
return dumpHexBytes(ByteBuffer.wrap(data), itemsPerLine, lineDelim,
itemDelim);
}
private static String dumpHexBytes(ByteBuffer data, int itemsPerLine,
String lineDelim, String itemDelim) {
StringBuilder sb = new StringBuilder();
if (data != null) {
data.mark();
int i = 0;
while (data.remaining() > 0) {
if (i % itemsPerLine == 0 && i != 0) {
sb.append(lineDelim);
}
sb.append(String.format("%02X", data.get())).append(itemDelim);
i++;
}
data.reset();
}
return sb.toString();
}
}

View file

@ -0,0 +1,180 @@
/*
* Copyright (c) 2019, 2022, 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.
*
* 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.
*/
/**
* @test
* @bug 8224997
* @summary ChaCha20-Poly1305 TLS cipher suite decryption throws ShortBufferException
* @library /test/lib
* @build jdk.test.lib.Convert
* @run main OutputSizeTest
*/
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.ChaCha20ParameterSpec;
import javax.crypto.spec.IvParameterSpec;
public class OutputSizeTest {
private static final SecureRandom SR = new SecureRandom();
public static void main(String args[]) throws Exception {
testCC20GetOutSize();
testCC20P1305GetOutSize();
testMultiPartAEADDec();
}
private static void testCC20GetOutSize()
throws GeneralSecurityException {
boolean result = true;
KeyGenerator kg = KeyGenerator.getInstance("ChaCha20", "SunJCE");
kg.init(256);
// ChaCha20 encrypt
Cipher cc20 = Cipher.getInstance("ChaCha20", "SunJCE");
cc20.init(Cipher.ENCRYPT_MODE, kg.generateKey(),
new ChaCha20ParameterSpec(getRandBuf(12), 10));
testOutLen(cc20, 0, 0);
testOutLen(cc20, 5, 5);
testOutLen(cc20, 5120, 5120);
// perform an update, then test with a final block
byte[] input = new byte[5120];
SR.nextBytes(input);
cc20.update(input);
testOutLen(cc20, 1024, 1024);
// Decryption lengths should be calculated the same way as encryption
cc20.init(Cipher.DECRYPT_MODE, kg.generateKey(),
new ChaCha20ParameterSpec(getRandBuf(12), 10));
testOutLen(cc20, 0, 0);
testOutLen(cc20, 5, 5);
testOutLen(cc20, 5120, 5120);
// perform an update, then test with a final block
cc20.update(input);
testOutLen(cc20, 1024, 1024);
}
private static void testCC20P1305GetOutSize()
throws GeneralSecurityException {
KeyGenerator kg = KeyGenerator.getInstance("ChaCha20", "SunJCE");
kg.init(256);
// ChaCha20 encrypt
Cipher cc20 = Cipher.getInstance("ChaCha20-Poly1305", "SunJCE");
cc20.init(Cipher.ENCRYPT_MODE, kg.generateKey(),
new IvParameterSpec(getRandBuf(12)));
// Encryption lengths are calculated as the input length plus the tag
// length (16).
testOutLen(cc20, 0, 16);
testOutLen(cc20, 5, 21);
testOutLen(cc20, 5120, 5136);
// perform an update, then test with a final block
byte[] input = new byte[5120];
SR.nextBytes(input);
cc20.update(input);
testOutLen(cc20, 1024, 1040);
// Decryption lengths are handled differently for AEAD mode. The length
// should be zero for anything up to and including the first 16 bytes
// (since that's the tag). Anything above that should be the input
// length plus any unprocessed input (via update calls), minus the
// 16 byte tag.
cc20.init(Cipher.DECRYPT_MODE, kg.generateKey(),
new IvParameterSpec(getRandBuf(12)));
testOutLen(cc20, 0, 0);
testOutLen(cc20, 5, 0);
testOutLen(cc20, 16, 0);
testOutLen(cc20, 5120, 5104);
// Perform an update, then test with the length of a final chunk
// of data.
cc20.update(input);
testOutLen(cc20, 1024, 6128);
}
private static void testMultiPartAEADDec() throws GeneralSecurityException {
KeyGenerator kg = KeyGenerator.getInstance("ChaCha20", "SunJCE");
kg.init(256);
Key key = kg.generateKey();
IvParameterSpec ivps = new IvParameterSpec(getRandBuf(12));
// Encrypt some data so we can test decryption.
byte[] pText = getRandBuf(2048);
ByteBuffer pTextBase = ByteBuffer.wrap(pText);
Cipher enc = Cipher.getInstance("ChaCha20-Poly1305", "SunJCE");
enc.init(Cipher.ENCRYPT_MODE, key, ivps);
ByteBuffer ctBuf = ByteBuffer.allocateDirect(
enc.getOutputSize(pText.length));
enc.doFinal(pTextBase, ctBuf);
// Create a new direct plain text ByteBuffer which will catch the
// decrypted data.
ByteBuffer ptBuf = ByteBuffer.allocateDirect(pText.length);
// Set the cipher text buffer limit to roughly half the data so we can
// do an update/final sequence.
ctBuf.position(0).limit(1024);
Cipher dec = Cipher.getInstance("ChaCha20-Poly1305", "SunJCE");
dec.init(Cipher.DECRYPT_MODE, key, ivps);
dec.update(ctBuf, ptBuf);
System.out.println("CTBuf: " + ctBuf);
System.out.println("PTBuf: " + ptBuf);
ctBuf.limit(ctBuf.capacity());
dec.doFinal(ctBuf, ptBuf);
ptBuf.flip();
pTextBase.flip();
System.out.println("PT Base:" + pTextBase);
System.out.println("PT Actual:" + ptBuf);
if (pTextBase.compareTo(ptBuf) != 0) {
StringBuilder sb = new StringBuilder();
sb.append("Plaintext mismatch: Original: ").
append(pTextBase.toString()).append("\nActual :").
append(ptBuf);
throw new RuntimeException(sb.toString());
}
}
private static void testOutLen(Cipher c, int inLen, int expOut) {
int actualOut = c.getOutputSize(inLen);
if (actualOut != expOut) {
throw new RuntimeException("Cipher " + c + ", in: " + inLen +
", expOut: " + expOut + ", actual: " + actualOut);
}
}
private static byte[] getRandBuf(int len) {
byte[] buf = new byte[len];
SR.nextBytes(buf);
return buf;
}
}

View file

@ -0,0 +1,187 @@
/*
* Copyright (c) 2025, 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.
*
* 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.
*/
/**
* @test
* @bug 8366833
* @summary Poly1305 does not always correctly update position for array-backed
* ByteBuffers after processMultipleBlocks
* @run main UpdateAADTest
*/
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.lang.foreign.MemorySegment;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.HexFormat;
public class UpdateAADTest {
private static final SecureRandom RAND;
private static final KeyGenerator CC20GEN;
private static final HexFormat HEX = HexFormat.of();
private static final byte[] TEST_KEY_BYTES = HEX.parseHex(
"3cb1283912536e4108c3094dc2940d0d020afbd7701de267bbfb359bc7d54dd7");
private static final byte[] TEST_NONCE_BYTES = HEX.parseHex(
"9bd647a43b6fa7826e2cc26d");
private static final byte[] TEST_AAD_BYTES =
"This is a bunch of additional data to throw into the mix.".
getBytes(StandardCharsets.UTF_8);
private static final byte[] TEST_INPUT_BYTES =
"This is a plaintext message".getBytes(StandardCharsets.UTF_8);
private static final byte[] TEST_CT_BYTES = HEX.parseHex(
"8536c999809f4b9d6a1594ee1084c751d1bd8a991e6a4b4ac26386f04b9a1303" +
"f40cbe6788d72af2d0c617");
private static final ByteBuffer EXPOUTBUF = ByteBuffer.wrap(TEST_CT_BYTES);
static {
try {
RAND = new SecureRandom();
CC20GEN = KeyGenerator.getInstance("ChaCha20");
} catch (GeneralSecurityException gse) {
throw new RuntimeException("Failed to init static JCE components",
gse);
}
}
public interface TestAction {
void runTest(ByteBuffer buffer) throws Exception;
}
public static void main(final String[] args) throws Exception {
ByteBuffer twoKBuf = ByteBuffer.allocate(2048);
ByteBuffer nonBABuf = ByteBuffer.allocate(1329);
System.out.println("----- Test 1: Baseline test -----");
System.out.println("Make an array backed buffer that is 16-byte " +
"aligned, treat all data as AAD and feed it to " +
" updateAAD.");
aadUpdateTest.runTest(twoKBuf);
System.out.println("----- Test 2: Non Block Aligned Offset -----");
System.out.println("Use the same buffer, but place the offset such " +
"that the remaining data is not block aligned.");
aadUpdateTest.runTest(twoKBuf.position(395));
System.out.println("----- Test 3: Non Block Aligned Buf/Off -----");
System.out.println("Make a buffer of non-block aligned size with an " +
"offset that keeps the remaining data non-block " +
"aligned.");
aadUpdateTest.runTest(nonBABuf.position(602));
System.out.println("----- Test 4: Aligned Buffer Slice -----");
System.out.println("Use a buffer of block aligned size, but slice " +
"the buffer such that the slice offset is part " +
"way into the original buffer.");
aadUpdateTest.runTest(twoKBuf.rewind().slice(1024,1024).position(42));
System.out.println("----- Test 5: Non-Aligned Buffer Slice -----");
System.out.println("Try the same test as #4, this time with " +
"non-block aligned buffers/slices.");
aadUpdateTest.runTest(nonBABuf.rewind().slice(347, 347).position(86));
System.out.println("----- Test 6: MemorySegment Buffer -----");
System.out.println("Make a ByteBuffer from an array-backed " +
"MemorySegment, and try updating");
MemorySegment mseg = MemorySegment.ofArray(new byte[2048]);
ByteBuffer msegBuf = mseg.asByteBuffer();
aadUpdateTest.runTest(msegBuf.position(55));
System.out.println("----- Test 7: Buffer of MemorySegment Slice -----");
System.out.println("Use a slice from the MemorySegment and create a " +
"buffer from that for testing");
MemorySegment msegSlice = mseg.asSlice(1024);
aadUpdateTest.runTest(msegSlice.asByteBuffer().position(55));
System.out.println("----- Test 8: MemorySegment Buffer Slice -----");
System.out.println("Create a slice from the ByteBuffer from the " +
"original MemorySegment.");
aadUpdateTest.runTest(msegBuf.rewind().slice(1024, 1024));
System.out.println("Test vector processing");
System.out.println("----------------------");
System.out.println("----- Test 9: AAD + Plaintext on buffer ------");
System.out.println("Place the AAD, followed by plaintext and verify " +
"the ciphertext");
// Create a ByteBuffer where the AAD and plaintext actually sit
// somewhere in the middle of the underlying array, with non-test-vector
// memory on either side of the data.
ByteBuffer vectorBuf = ByteBuffer.allocate(1024).position(600).
put(TEST_AAD_BYTES).put(TEST_INPUT_BYTES).flip().position(600);
vectorTest.runTest(vectorBuf);
System.out.println("----- Test 10: AAD + Plaintext on slice -----");
System.out.println("Perform the same test, this time on a slice" +
"of the test vector buffer");
ByteBuffer vectorSlice = vectorBuf.slice(600,
TEST_AAD_BYTES.length + TEST_INPUT_BYTES.length);
vectorTest.runTest(vectorSlice);
}
// Simple test callback for taking a ByteBuffer and throwing all
// remaining bytes into an updateAAD call.
public static TestAction aadUpdateTest = buffer -> {
SecretKey key = CC20GEN.generateKey();
byte[] nonce = new byte[12];
RAND.nextBytes(nonce);
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(nonce));
cipher.updateAAD(buffer);
// Per the API the buffer's position and limit should be equal
if (buffer.position() != buffer.limit()) {
throw new RuntimeException("Buffer position and limit " +
"should be equal but are not: p = " +
buffer.position() + ", l = " + buffer.limit());
}
};
// Test callback for making sure that the updateAAD method, when
// put in with a complete encryption operation still gets the
// expected answer.
public static TestAction vectorTest = buffer -> {
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305");
cipher.init(Cipher.ENCRYPT_MODE,
new SecretKeySpec(TEST_KEY_BYTES, "ChaCha20"),
new IvParameterSpec(TEST_NONCE_BYTES));
ByteBuffer outbuf = ByteBuffer.allocate(cipher.getOutputSize(
TEST_INPUT_BYTES.length));
// Adjust the limit to be the end of the aad
int origLim = buffer.limit();
buffer.limit(buffer.position() + TEST_AAD_BYTES.length);
cipher.updateAAD(buffer);
buffer.limit(origLim);
cipher.doFinal(buffer, outbuf);
if (!outbuf.flip().equals(EXPOUTBUF)) {
throw new RuntimeException("Output data mismatch");
}
};
}

View file

@ -0,0 +1,259 @@
/*
* Copyright (c) 2018, 2025, 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.
*
* 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.
*/
/*
* @test
* @bug 8153029 8360463 8368984
* @library /test/lib
* @run main ChaCha20CipherUnitTest
* @summary Unit test for com.sun.crypto.provider.ChaCha20Cipher.
*/
import java.nio.ByteBuffer;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.HexFormat;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.ChaCha20ParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import jdk.test.lib.Utils;
public class ChaCha20CipherUnitTest {
private static final byte[] NONCE
= HexFormat.of().parseHex("012345670123456701234567");
private static final SecretKeySpec KEY = new SecretKeySpec(
HexFormat.of().parseHex("0123456701234567012345670123456701234567012345670123456701234567"),
"ChaCha20");
private static final ChaCha20ParameterSpec CHACHA20_PARAM_SPEC
= new ChaCha20ParameterSpec(NONCE, 0);
private static final IvParameterSpec IV_PARAM_SPEC
= new IvParameterSpec(NONCE);
public static void main(String[] args) throws Exception {
testTransformations();
testInit();
testAEAD();
testGetBlockSize();
}
private static void testTransformations() throws Exception {
System.out.println("== transformations ==");
Class NSAE = NoSuchAlgorithmException.class;
Class NSPE = NoSuchPaddingException.class;
checkTransformation("ChaCha20", null);
checkTransformation("ChaCha20/None/NoPadding", null);
checkTransformation("ChaCha20/None//", NSAE);
checkTransformation("ChaCha20/ECB/NoPadding", NSAE);
checkTransformation("ChaCha20/None/PKCS5Padding", NSPE);
checkTransformation("ChaCha20-Poly1305", null);
checkTransformation("ChaCha20-Poly1305/None/NoPadding", null);
checkTransformation("ChaCha20-Poly1305/None//", NSAE);
checkTransformation("ChaCha20-Poly1305/ECB/NoPadding", NSAE);
checkTransformation("ChaCha20-Poly1305/None/PKCS5Padding", NSPE);
}
private static void checkTransformation(String transformation, Class exCls)
throws Exception {
try {
Cipher.getInstance(transformation,
System.getProperty("test.provider.name", "SunJCE"));
if (exCls != null) {
throw new RuntimeException("Expected Exception not thrown: " +
exCls);
} else {
System.out.println(transformation + ": pass");
}
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
if (e.getClass() != exCls) {
throw new RuntimeException("Unexpected Exception", e);
} else {
System.out.println(transformation + ": got expected " +
exCls.getName());
}
}
}
private static void testInit() throws Exception {
testInitOnCrypt(Cipher.ENCRYPT_MODE);
testInitOnCrypt(Cipher.DECRYPT_MODE);
testInitOnWrap(Cipher.WRAP_MODE);
testInitOnWrap(Cipher.UNWRAP_MODE);
}
private static void testInitOnCrypt(int opMode) throws Exception {
System.out.println("== init (" + getOpModeName(opMode) + ") ==");
Cipher.getInstance("ChaCha20").init(opMode, KEY, CHACHA20_PARAM_SPEC);
Cipher.getInstance("ChaCha20").init(opMode, KEY,
CHACHA20_PARAM_SPEC, new SecureRandom());
try {
Cipher.getInstance("ChaCha20").init(opMode, KEY, IV_PARAM_SPEC);
throw new RuntimeException("ChaCha20ParameterSpec is needed");
} catch (InvalidAlgorithmParameterException e) {
System.out.println("Expected " + e);
}
Cipher.getInstance("ChaCha20-Poly1305").init(opMode, KEY,
IV_PARAM_SPEC);
Cipher.getInstance("ChaCha20-Poly1305").init(opMode, KEY,
IV_PARAM_SPEC, new SecureRandom());
try {
Cipher.getInstance("ChaCha20-Poly1305").init(opMode, KEY,
CHACHA20_PARAM_SPEC);
throw new RuntimeException("IvParameterSpec is needed");
} catch (InvalidAlgorithmParameterException e) {
System.out.println("Expected " + e);
}
AlgorithmParameters algorithmParameters =
AlgorithmParameters.getInstance("ChaCha20-Poly1305");
algorithmParameters.init(
new byte[] { 4, 12, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8 });
try {
Cipher.getInstance("ChaCha20").init(opMode, KEY,
algorithmParameters, new SecureRandom());
throw new RuntimeException(
"ChaCha20 cipher doesn't accept AlgorithmParameters");
} catch (InvalidAlgorithmParameterException e) {
System.out.println("Expected " + e);
}
Cipher.getInstance("ChaCha20-Poly1305").init(opMode, KEY,
algorithmParameters, new SecureRandom());
}
private static void testInitOnWrap(int opMode) throws Exception {
String opModeName = getOpModeName(opMode);
System.out.println("== init (" + opModeName + ") ==");
Cipher chacha20Cipher = Cipher.getInstance("ChaCha20");
try {
chacha20Cipher.init(opMode, KEY, new SecureRandom());
throw new RuntimeException(
"Unexpected opration mode: " + opModeName);
} catch (Exception e) {
if (e instanceof UnsupportedOperationException) {
System.out.println("Expected " + e);
} else {
throw new RuntimeException("Unexpected exception: " + e);
}
}
}
private static void testAEAD() throws Exception {
byte[] expectedPlainttext = HexFormat.of().parseHex("01234567");
byte[] ciphertext = testUpdateAAD(Cipher.ENCRYPT_MODE, expectedPlainttext);
byte[] plaintext = testUpdateAAD(Cipher.DECRYPT_MODE, ciphertext);
if (!Arrays.equals(plaintext, expectedPlainttext)) {
System.out.println("ciphertext: " + Arrays.toString(ciphertext));
System.out.println("plaintext: " + Arrays.toString(plaintext));
throw new RuntimeException("AEAD failed");
}
}
private static byte[] testUpdateAAD(int opMode, byte[] input)
throws Exception {
String opModeName = getOpModeName(opMode);
System.out.println("== updateAAD (" + opModeName + ") ==");
byte[] aad = HexFormat.of().parseHex("0000");
ByteBuffer aadBuf = ByteBuffer.wrap(aad);
Cipher cipher = Cipher.getInstance("ChaCha20");
cipher.init(opMode, KEY, CHACHA20_PARAM_SPEC);
try {
cipher.updateAAD(aadBuf);
throw new RuntimeException("ChaCha20 cipher cannot apply AAD");
} catch (IllegalStateException e) {
System.out.println("Expected " + e);
}
Cipher aeadCipher = Cipher.getInstance("ChaCha20-Poly1305");
try {
aeadCipher.updateAAD(aadBuf);
throw new RuntimeException(
"Cannot update AAD on uninitialized Cipher");
} catch (IllegalStateException e) {
System.out.println("Expected " + e);
}
aeadCipher.init(opMode, KEY, IV_PARAM_SPEC);
aeadCipher.update(input);
try {
aeadCipher.updateAAD(aad);
throw new RuntimeException(
"Cannot update AAD after plaintext/cipertext update");
} catch (IllegalStateException e) {
System.out.println("Expected " + e);
}
aeadCipher = Cipher.getInstance("ChaCha20-Poly1305");
aeadCipher.init(opMode, KEY, IV_PARAM_SPEC);
aeadCipher.updateAAD(aadBuf);
return aeadCipher.doFinal(input);
}
private static void testGetBlockSize() throws Exception {
testGetBlockSize(Cipher.ENCRYPT_MODE);
testGetBlockSize(Cipher.DECRYPT_MODE);
}
private static void testGetBlockSize(int opMode) throws Exception {
System.out.println("== getBlockSize (" + getOpModeName(opMode) + ") ==");
Cipher cipher = Cipher.getInstance("ChaCha20");
cipher.init(opMode, KEY, CHACHA20_PARAM_SPEC);
if (cipher.getBlockSize() != 0) {
throw new RuntimeException("Block size must be 0");
}
}
private static String getOpModeName(int opMode) {
switch (opMode) {
case Cipher.ENCRYPT_MODE:
return "ENCRYPT";
case Cipher.DECRYPT_MODE:
return "DECRYPT";
case Cipher.WRAP_MODE:
return "WRAP";
case Cipher.UNWRAP_MODE:
return "UNWRAP";
default:
return "";
}
}
}

View file

@ -0,0 +1,148 @@
/*
* Copyright (c) 2018, 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.
*
* 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.
*/
/*
* @test
* @bug 8153029
* @library /test/lib
* @run main ChaCha20Poly1305ParametersUnitTest
* @summary Unit test for com.sun.crypto.provider.ChaCha20Poly1305Parameters.
*/
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import javax.crypto.spec.ChaCha20ParameterSpec;
import javax.crypto.spec.IvParameterSpec;
public class ChaCha20Poly1305ParametersUnitTest {
private static final String ALGORITHM = "ChaCha20-Poly1305";
private static final byte[] NONCE = {
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8 };
private static final byte[] PARAM = {
4, 12, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8 };
private static final byte[] BAD_NONCE = {
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
private static final byte[] BAD_PARAM = {
4, 13, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public static void main(String[] args) throws Exception {
testInit();
testGetParameterSpec();
testGetEncoded();
}
private static void testInit() throws Exception {
System.out.println("== init ==");
AlgorithmParameters ap = AlgorithmParameters.getInstance(ALGORITHM);
ap.init(new IvParameterSpec(NONCE));
System.out.println("AlgorithmParameters: " + ap);
ap = AlgorithmParameters.getInstance(ALGORITHM);
ap.init(PARAM);
ap = AlgorithmParameters.getInstance(ALGORITHM);
try {
ap.init(new ChaCha20ParameterSpec(NONCE, 0));
throw new RuntimeException("IvParameterSpec is needed");
} catch (InvalidParameterSpecException e) {
System.out.println("Expected " + e);
}
ap = AlgorithmParameters.getInstance(ALGORITHM);
try {
ap.init(new IvParameterSpec(BAD_NONCE));
throw new RuntimeException("Nonce must be 96 bits in length");
} catch (InvalidParameterSpecException e) {
System.out.println("Expected " + e);
}
ap = AlgorithmParameters.getInstance(ALGORITHM);
try {
ap.init(BAD_PARAM);
throw new RuntimeException("Nonce must be 96 bits in length");
} catch (IOException e) {
System.out.println("Expected " + e);
}
}
private static void testGetParameterSpec() throws Exception {
System.out.println("== getParameterSpec ==");
AlgorithmParameters ap = AlgorithmParameters.getInstance(ALGORITHM);
ap.init(PARAM);
IvParameterSpec paramSpec = ap.getParameterSpec(IvParameterSpec.class);
byte[] nonce = paramSpec.getIV();
System.out.println("Nonce: " + Arrays.toString(nonce));
Arrays.equals(nonce, NONCE);
try {
ap.getParameterSpec(ChaCha20ParameterSpec.class);
throw new RuntimeException("IvParameterSpec is needed");
} catch (InvalidParameterSpecException e) {
System.out.println("Expected " + e);
}
}
private static void testGetEncoded() throws Exception {
System.out.println("== getEncoded ==");
AlgorithmParameters ap = AlgorithmParameters.getInstance(ALGORITHM);
ap.init(PARAM);
byte[] defaultFormatEncoded = ap.getEncoded();
System.out.println("Default format encoding: "
+ Arrays.toString(defaultFormatEncoded));
if (!Arrays.equals(defaultFormatEncoded, PARAM)) {
throw new RuntimeException("Default format encoding failed");
}
byte[] asn1FormatEncoded = ap.getEncoded("ASN.1");
System.out.println("ASN.1 format encoding: "
+ Arrays.toString(asn1FormatEncoded));
if (!Arrays.equals(asn1FormatEncoded, PARAM)) {
throw new RuntimeException("ASN.1 format encoding failed");
}
byte[] nullFormatEncoded = ap.getEncoded(null);
System.out.println("Null format encoding: "
+ Arrays.toString(nullFormatEncoded));
if (!Arrays.equals(nullFormatEncoded, PARAM)) {
throw new RuntimeException("Null format encoding failed");
}
try {
ap.getEncoded("BAD");
throw new RuntimeException("Format must be ASN.1");
} catch (IOException e) {
System.out.println("Expected " + e);
}
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2018, 2022, 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.
*
* 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.
*/
/*
* @test
* @bug 8153029
* @modules java.base/com.sun.crypto.provider
* @run main java.base/com.sun.crypto.provider.Poly1305UnitTest
* @summary Unit test for com.sun.crypto.provider.Poly1305.
*/
/*
* @test
* @key randomness
* @modules java.base/com.sun.crypto.provider
* @run main java.base/com.sun.crypto.provider.Poly1305IntrinsicFuzzTest
* @summary Unit test for com.sun.crypto.provider.Poly1305.
*/
/*
* @test
* @modules java.base/com.sun.crypto.provider
* @run main java.base/com.sun.crypto.provider.Poly1305KAT
* @summary Unit test for com.sun.crypto.provider.Poly1305.
*/
/*
* @test
* @key randomness
* @modules java.base/com.sun.crypto.provider
* @summary Unit test for IntrinsicCandidate in com.sun.crypto.provider.Poly1305.
* @run main/othervm -Xcomp -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+ForceUnreachable java.base/com.sun.crypto.provider.Poly1305IntrinsicFuzzTest
*/
/*
* @test
* @modules java.base/com.sun.crypto.provider
* @summary Unit test for IntrinsicCandidate in com.sun.crypto.provider.Poly1305.
* @run main/othervm -Xcomp -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+ForceUnreachable java.base/com.sun.crypto.provider.Poly1305KAT
*/
package com.sun.crypto.provider.Cipher.ChaCha20;
public class Poly1305UnitTestDriver {
static public void main(String[] args) {
System.out.println("Passed");
}
}

View file

@ -0,0 +1,121 @@
/*
* Copyright (c) 2022, Intel Corporation. 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.
*
* 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.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
import javax.crypto.spec.SecretKeySpec;
// This test case relies on the fact that single-byte Poly1305.engineUpdate(byte) does not have an intrinsic
// In this way we can compare if the intrinsic and pure java produce same result
// This test case is NOT entirely deterministic, it uses a random seed for pseudo-random number generator
// If a failure occurs, hardcode the seed to make the test case deterministic
public class Poly1305IntrinsicFuzzTest {
public static void main(String[] args) throws Exception {
//Note: it might be useful to increase this number during development of new Poly1305 intrinsics
final int repeat = 1000;
for (int i = 0; i < repeat; i++) {
run();
}
System.out.println("Fuzz Success");
}
public static void run() throws Exception {
Random rnd = new Random();
long seed = rnd.nextLong();
rnd.setSeed(seed);
byte[] key = new byte[32];
rnd.nextBytes(key);
int msgLen = rnd.nextInt(128, 4096); // x86_64 intrinsic requires 256 bytes minimum
byte[] message = new byte[msgLen];
rnd.nextBytes(message);
Poly1305 authenticator = new Poly1305();
Poly1305 authenticatorSlow = new Poly1305();
if (authenticator.engineGetMacLength() != 16) {
throw new RuntimeException("The length of Poly1305 MAC must be 16-bytes.");
}
authenticator.engineInit(new SecretKeySpec(key, 0, 32, "Poly1305"), null);
authenticatorSlow.engineInit(new SecretKeySpec(key, 0, 32, "Poly1305"), null);
if (rnd.nextBoolean() && message.length > 16) {
// Prime just the buffer and/or accumulator (buffer can keep at most 16 bytes from previous engineUpdate)
int initDataLen = rnd.nextInt(1, 16);
int initDataOffset = rnd.nextInt(0, message.length - initDataLen);
fastUpdate(authenticator, rnd, message, initDataOffset, initDataLen);
slowUpdate(authenticatorSlow, message, initDataOffset, initDataLen);
}
if (rnd.nextBoolean()) {
// Multiple calls to engineUpdate
int initDataOffset = rnd.nextInt(0, message.length);
fastUpdate(authenticator, rnd, message, initDataOffset, message.length - initDataOffset);
slowUpdate(authenticatorSlow, message, initDataOffset, message.length - initDataOffset);
}
fastUpdate(authenticator, rnd, message, 0, message.length);
slowUpdate(authenticatorSlow, message, 0, message.length);
byte[] tag = authenticator.engineDoFinal();
byte[] tagSlow = authenticatorSlow.engineDoFinal();
if (!Arrays.equals(tag, tagSlow)) {
throw new RuntimeException("[Seed "+seed+"] Tag mismatch: " + Arrays.toString(tag) + " != " + Arrays.toString(tagSlow));
}
}
static void slowUpdate(Poly1305 authenticator, byte[] message, int offset, int len) {
for (int i = offset; i < offset + len; i++) {
authenticator.engineUpdate(message[i]);
}
}
static void fastUpdate(Poly1305 authenticator, Random rnd, byte[] message, int offset, int len) {
ByteBuffer buf;
switch(rnd.nextInt(4)) {
case 0: // byte[]
authenticator.engineUpdate(message, offset, len);
break;
case 1: // ByteArray with backing array
buf = ByteBuffer.wrap(message, offset, len);
authenticator.engineUpdate(buf);
break;
case 2: // ByteArray with backing array (non-zero position)
buf = ByteBuffer.wrap(message, 0, len+offset)
.position(offset);
authenticator.engineUpdate(buf);
break;
case 3: // ByteArray without backing array (wont be sent to intrinsic)
buf = ByteBuffer.wrap(message, offset, len)
.asReadOnlyBuffer();
authenticator.engineUpdate(buf);
break;
}
}
}

View file

@ -0,0 +1,199 @@
/*
* Copyright (c) 2022, Intel Corporation. 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.
*
* 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.*;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.crypto.spec.SecretKeySpec;
public class Poly1305KAT {
public static class TestData {
public TestData(String name, String keyStr, String inputStr, String outStr) {
HexFormat hex = HexFormat.of();
testName = Objects.requireNonNull(name);
key = hex.parseHex(Objects.requireNonNull(keyStr));
input = hex.parseHex(Objects.requireNonNull(inputStr));
expOutput = hex.parseHex(Objects.requireNonNull(outStr));
}
public final String testName;
public final byte[] key;
public final byte[] input;
public final byte[] expOutput;
}
public static final List<TestData> testList = new LinkedList<TestData>() {{
add(new TestData("RFC 7539 A.3 Test Vector #1",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000" +
"0000000000000000000000000000000000000000000000000000000000000000",
"00000000000000000000000000000000"));
add(new TestData("RFC 7539 A.3 Test Vector #2",
"0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e",
"416e79207375626d697373696f6e20746f20746865204945544620696e74656e" +
"6465642062792074686520436f6e7472696275746f7220666f72207075626c69" +
"636174696f6e20617320616c6c206f722070617274206f6620616e2049455446" +
"20496e7465726e65742d4472616674206f722052464320616e6420616e792073" +
"746174656d656e74206d6164652077697468696e2074686520636f6e74657874" +
"206f6620616e204945544620616374697669747920697320636f6e7369646572" +
"656420616e20224945544620436f6e747269627574696f6e222e205375636820" +
"73746174656d656e747320696e636c756465206f72616c2073746174656d656e" +
"747320696e20494554462073657373696f6e732c2061732077656c6c20617320" +
"7772697474656e20616e6420656c656374726f6e696320636f6d6d756e696361" +
"74696f6e73206d61646520617420616e792074696d65206f7220706c6163652c" +
"207768696368206172652061646472657373656420746f",
"36e5f6b5c5e06070f0efca96227a863e"));
add(new TestData("RFC 7539 A.3 Test Vector #3",
"36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000",
"416e79207375626d697373696f6e20746f20746865204945544620696e74656e" +
"6465642062792074686520436f6e7472696275746f7220666f72207075626c69" +
"636174696f6e20617320616c6c206f722070617274206f6620616e2049455446" +
"20496e7465726e65742d4472616674206f722052464320616e6420616e792073" +
"746174656d656e74206d6164652077697468696e2074686520636f6e74657874" +
"206f6620616e204945544620616374697669747920697320636f6e7369646572" +
"656420616e20224945544620436f6e747269627574696f6e222e205375636820" +
"73746174656d656e747320696e636c756465206f72616c2073746174656d656e" +
"747320696e20494554462073657373696f6e732c2061732077656c6c20617320" +
"7772697474656e20616e6420656c656374726f6e696320636f6d6d756e696361" +
"74696f6e73206d61646520617420616e792074696d65206f7220706c6163652c" +
"207768696368206172652061646472657373656420746f",
"f3477e7cd95417af89a6b8794c310cf0"));
add(new TestData("RFC 7539 A.3 Test Vector #4",
"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
"2754776173206272696c6c69672c20616e642074686520736c6974687920746f" +
"7665730a446964206779726520616e642067696d626c6520696e207468652077" +
"6162653a0a416c6c206d696d737920776572652074686520626f726f676f7665" +
"732c0a416e6420746865206d6f6d65207261746873206f757467726162652e",
"4541669a7eaaee61e708dc7cbcc5eb62"));
add(new TestData("RFC 7539 A.3 Test Vector #5: If one uses 130-bit partial reduction, does the code handle the case where partially reducedfinal result is not fully reduced?",
"0200000000000000000000000000000000000000000000000000000000000000",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"03000000000000000000000000000000"));
add(new TestData("RFC 7539 A.3 Test Vector #6: What happens if addition of s overflows modulo 2^128?",
"02000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"02000000000000000000000000000000",
"03000000000000000000000000000000"));
add(new TestData("RFC 7539 A.3 Test Vector #7: What happens if data limb is all ones and there is carry from lower limb?",
"0100000000000000000000000000000000000000000000000000000000000000",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +
"11000000000000000000000000000000",
"05000000000000000000000000000000"));
add(new TestData("RFC 7539 A.3 Test Vector #8: What happens if final result from polynomial part is exactly 2^130-5?",
"0100000000000000000000000000000000000000000000000000000000000000",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE" +
"01010101010101010101010101010101",
"00000000000000000000000000000000"));
add(new TestData("RFC 7539 A.3 Test Vector #9: What happens if final result from polynomial part is exactly 2^130-6?",
"0200000000000000000000000000000000000000000000000000000000000000",
"FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
add(new TestData("RFC 7539 A.3 Test Vector #10: What happens if 5*H+L-type reduction produces 131-bit intermediate result?",
"0100000000000000040000000000000000000000000000000000000000000000",
"E33594D7505E43B900000000000000003394D7505E4379CD0100000000000000" +
"0000000000000000000000000000000001000000000000000000000000000000",
"14000000000000005500000000000000"));
add(new TestData("RFC 7539 A.3 Test Vector #11: What happens if 5*H+L-type reduction produces 131-bit final result?",
"0100000000000000040000000000000000000000000000000000000000000000",
"E33594D7505E43B900000000000000003394D7505E4379CD0100000000000000" +
"00000000000000000000000000000000",
"13000000000000000000000000000000"));
}};
public static void main(String args[]) throws Exception {
int testsPassed = 0;
int testNumber = 0;
for (TestData test : testList) {
System.out.println("*** Test " + ++testNumber + ": " +
test.testName);
if (runSingleTest(test)) {
testsPassed++;
}
}
System.out.println();
if (testsPassed != testNumber) {
throw new RuntimeException("One or more tests failed. " +
"Check output for details");
}
}
private static boolean runSingleTest(TestData testData) throws Exception {
Poly1305 authenticator = new Poly1305(false);
authenticator.engineInit(new SecretKeySpec(testData.key, 0, testData.key.length, "Poly1305"), null);
authenticator.engineUpdate(testData.input, 0, testData.input.length);
byte[] tag = authenticator.engineDoFinal();
if (!Arrays.equals(tag, testData.expOutput)) {
System.out.println("ERROR - Output Mismatch!");
System.out.println("Expected:\n" +
dumpHexBytes(testData.expOutput, testData.expOutput.length, "\n", " "));
System.out.println("Actual:\n" +
dumpHexBytes(tag, tag.length, "\n", " "));
System.out.println();
return false;
}
return true;
}
/**
* Dump the hex bytes of a buffer into string form.
*
* @param data The array of bytes to dump to stdout.
* @param itemsPerLine The number of bytes to display per line
* if the {@code lineDelim} character is blank then all bytes
* will be printed on a single line.
* @param lineDelim The delimiter between lines
* @param itemDelim The delimiter between bytes
*
* @return The hexdump of the byte array
*/
private static String dumpHexBytes(byte[] data, int itemsPerLine,
String lineDelim, String itemDelim) {
return dumpHexBytes(ByteBuffer.wrap(data), itemsPerLine, lineDelim,
itemDelim);
}
private static String dumpHexBytes(ByteBuffer data, int itemsPerLine,
String lineDelim, String itemDelim) {
StringBuilder sb = new StringBuilder();
if (data != null) {
data.mark();
int i = 0;
while (data.remaining() > 0) {
if (i % itemsPerLine == 0 && i != 0) {
sb.append(lineDelim);
}
sb.append(String.format("%02X", data.get())).append(itemDelim);
i++;
}
data.reset();
}
return sb.toString();
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright (c) 2018, 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.
*
* 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.nio.ByteBuffer;
import java.util.Arrays;
import javax.crypto.spec.SecretKeySpec;
public class Poly1305UnitTest {
public static void main(String[] args) throws Exception {
byte[] key = new byte[] {
28, -110, 64, -91, -21, 85, -45, -118,
-13, 51, -120, -122, 4, -10, -75, -16,
71, 57, 23, -63, 64, 43, -128, 9,
-99, -54, 92, -68, 32, 112, 117, -64
};
Poly1305 authenticator = new Poly1305();
if (authenticator.engineGetMacLength() != 16) {
throw new RuntimeException(
"The length of Poly1305 MAC must be 16-bytes.");
}
authenticator.engineInit(new SecretKeySpec(key, 0, 32,
"Poly1305"), null);
byte[] message = new byte[] {
39, 84, 119, 97, 115, 32, 98, 114,
105, 108, 108, 105, 103, 44, 32, 97,
110, 100, 32, 116, 104, 101, 32, 115,
108, 105, 116, 104, 121, 32, 116, 111,
118, 101, 115, 10, 68, 105, 100, 32,
103, 121, 114, 101, 32, 97, 110, 100,
32, 103, 105, 109, 98, 108, 101, 32,
105, 110, 32, 116, 104, 101, 32, 119,
97, 98, 101, 58, 10, 65, 108, 108,
32, 109, 105, 109, 115, 121, 32, 119,
101, 114, 101, 32, 116, 104, 101, 32,
98, 111, 114, 111, 103, 111, 118, 101,
115, 44, 10, 65, 110, 100, 32, 116,
104, 101, 32, 109, 111, 109, 101, 32,
114, 97, 116, 104, 115, 32, 111, 117,
116, 103, 114, 97, 98, 101, 46
};
authenticator.engineUpdate(
ByteBuffer.wrap(Arrays.copyOfRange(message, 0, 8)));
authenticator.engineUpdate(message, 8, 104);
authenticator.engineUpdate(message, 112, 7);
for (int i = 119; i < message.length; i++) {
authenticator.engineUpdate(message[i]);
}
byte[] tag = authenticator.engineDoFinal();
byte[] expectedTag = new byte[] {
69, 65, 102, -102, 126, -86, -18, 97,
-25, 8, -36, 124, -68, -59, -21, 98
};
if (!Arrays.equals(tag, expectedTag)) {
throw new RuntimeException(
"Unexpected tag: " + Arrays.toString(tag));
}
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2017, 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.
*
* 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.
*/
/*
* @test
* @modules java.base/com.sun.crypto.provider:+open
* @run main/othervm DESKeyCleanupTest
* @summary Verify that key storage is cleared
*/
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/**
* Test that the array holding the key bytes is cleared when it is
* no longer referenced by the key.
*/
public class DESKeyCleanupTest {
private final static String SunJCEProvider = "SunJCE";
public static void main(String[] args) throws Exception {
testCleanupSecret("DES");
testCleanupSecret("DESede");
}
static void testCleanupSecret(String algorithm) throws Exception {
KeyGenerator desGen = KeyGenerator.getInstance(algorithm, SunJCEProvider);
SecretKey key = desGen.generateKey();
// Break into the implementation to observe the key byte array.
Class<?> keyClass = key.getClass();
Field keyField = keyClass.getDeclaredField("key");
keyField.setAccessible(true);
byte[] array = (byte[])keyField.get(key);
byte[] zeros = new byte[array.length];
do {
// Wait for array to be cleared; if not cleared test will timeout
System.out.printf("%s array: %s%n", algorithm, Arrays.toString(array));
key = null;
System.gc(); // attempt to reclaim the key
} while (Arrays.compare(zeros, array) != 0);
System.out.printf("%s array: %s%n", algorithm, Arrays.toString(array));
Reference.reachabilityFence(key); // Keep key alive
Reference.reachabilityFence(array); // Keep array alive
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2013, 2015, 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.
*
* 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.
*/
/*
* @test
* @bug 6755701
* @summary Change SecretKeyFactory.generateSecret to allow SecretKeySpec to
* be passed and used for creating a DES and DESede keys. This avoids the error
* of "InvalidKeySpecException: Inappropriate key specification"
* @author Anthony Scarpino
*/
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
public class DESSecretKeySpec {
public static void main(String arg[]) throws Exception {
Cipher c;
byte[] key = new byte[]{'1','2','3','4','5','6','7','8',
'1','2','3','4','5','6','7','8',
'1','2','3','4','5','6','7','8'};
System.out.println("Testing DES key");
SecretKeySpec skey = new SecretKeySpec(key, "DES");
c = Cipher.getInstance("DES/CBC/PKCS5Padding", "SunJCE");
SecretKeyFactory.getInstance("DES", "SunJCE").generateSecret(skey);
System.out.println("Testing DESede key");
skey = new SecretKeySpec(key, "DESede");
c = Cipher.getInstance("DESede/CBC/PKCS5Padding", "SunJCE");
SecretKeyFactory.getInstance("TripleDES", "SunJCE").generateSecret(skey);
}
}

Some files were not shown because too many files have changed in this diff Show more