[pkg-eucalyptus-commits] r25 - / openjdk-crypto openjdk-crypto/trunk openjdk-crypto/trunk/debian openjdk-crypto/trunk/src openjdk-crypto/trunk/src/main openjdk-crypto/trunk/src/main/java openjdk-crypto/trunk/src/main/java/javax openjdk-crypto/trunk/src/main/java/javax/crypto
Chris Grzegorczyk
grze-guest at alioth.debian.org
Sat Mar 13 04:23:31 UTC 2010
Author: grze-guest
Date: 2010-03-13 04:23:29 +0000 (Sat, 13 Mar 2010)
New Revision: 25
Added:
openjdk-crypto/
openjdk-crypto/trunk/
openjdk-crypto/trunk/debian/
openjdk-crypto/trunk/debian/README.Debian
openjdk-crypto/trunk/debian/build-jars
openjdk-crypto/trunk/debian/build.xml
openjdk-crypto/trunk/debian/changelog
openjdk-crypto/trunk/debian/compat
openjdk-crypto/trunk/debian/control
openjdk-crypto/trunk/debian/copyright
openjdk-crypto/trunk/debian/rules
openjdk-crypto/trunk/src/
openjdk-crypto/trunk/src/main/
openjdk-crypto/trunk/src/main/java/
openjdk-crypto/trunk/src/main/java/javax/
openjdk-crypto/trunk/src/main/java/javax/crypto/
openjdk-crypto/trunk/src/main/java/javax/crypto/BadPaddingException.java
openjdk-crypto/trunk/src/main/java/javax/crypto/Cipher.java
openjdk-crypto/trunk/src/main/java/javax/crypto/CipherInputStream.java
openjdk-crypto/trunk/src/main/java/javax/crypto/CipherOutputStream.java
openjdk-crypto/trunk/src/main/java/javax/crypto/CipherSpi.java
openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoAllPermission.java
openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPermission.java
openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPermissions.java
openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPolicyParser.java
openjdk-crypto/trunk/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanism.java
openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanismException.java
openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanismSpi.java
openjdk-crypto/trunk/src/main/java/javax/crypto/IllegalBlockSizeException.java
openjdk-crypto/trunk/src/main/java/javax/crypto/JceSecurity.java
openjdk-crypto/trunk/src/main/java/javax/crypto/KeyAgreement.java
openjdk-crypto/trunk/src/main/java/javax/crypto/KeyAgreementSpi.java
openjdk-crypto/trunk/src/main/java/javax/crypto/KeyGenerator.java
openjdk-crypto/trunk/src/main/java/javax/crypto/KeyGeneratorSpi.java
openjdk-crypto/trunk/src/main/java/javax/crypto/Mac.java
openjdk-crypto/trunk/src/main/java/javax/crypto/MacSpi.java
openjdk-crypto/trunk/src/main/java/javax/crypto/NoSuchPaddingException.java
openjdk-crypto/trunk/src/main/java/javax/crypto/NullCipher.java
openjdk-crypto/trunk/src/main/java/javax/crypto/NullCipherSpi.java
openjdk-crypto/trunk/src/main/java/javax/crypto/SealedObject.java
openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKey.java
openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKeyFactory.java
openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKeyFactorySpi.java
openjdk-crypto/trunk/src/main/java/javax/crypto/ShortBufferException.java
openjdk-crypto/trunk/src/main/resources/
Log:
very early stab at openjdk-crypto package
Added: openjdk-crypto/trunk/debian/README.Debian
===================================================================
--- openjdk-crypto/trunk/debian/README.Debian (rev 0)
+++ openjdk-crypto/trunk/debian/README.Debian 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,6 @@
+openjdk-crypto for Debian
+-------------------------
+
+<possible notes regarding this package - if none, delete this file>
+
+ -- Chris Grzegorczyk <grze at eucalyptus.com> Fri, 12 Mar 2010 18:59:34 -0800
Added: openjdk-crypto/trunk/debian/build-jars
===================================================================
--- openjdk-crypto/trunk/debian/build-jars (rev 0)
+++ openjdk-crypto/trunk/debian/build-jars 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,43 @@
+/usr/share/java/ant.jar
+/usr/share/java/antlr.jar
+/usr/share/java/aopalliance.jar
+/usr/share/java/asm3-commons.jar
+/usr/share/java/asm3.jar
+/usr/share/java/asm-attrs.jar
+/usr/share/java/backport-util-concurrent.jar
+/usr/share/java/bsh.jar
+/usr/share/java/catalina.jar
+/usr/share/java/cglib.jar
+/usr/share/java/commons-attributes-api.jar
+/usr/share/java/commons-beanutils.jar
+/usr/share/java/commons-cli.jar
+/usr/share/java/commons-collections3.jar
+/usr/share/java/commons-io.jar
+/usr/share/java/commons-jxpath.jar
+/usr/share/java/commons-lang.jar
+/usr/share/java/commons-logging.jar
+/usr/share/java/commons-pool.jar
+/usr/share/java/dom4j.jar
+/usr/share/java/el-api-2.1.jar
+/usr/share/java/geronimo-ejb-3.0-spec.jar
+/usr/share/java/geronimo-interceptor-3.0-spec.jar
+/usr/share/java/geronimo-j2ee-connector-1.5-spec.jar
+/usr/share/java/geronimo-jacc-1.1-spec.jar
+/usr/share/java/geronimo-jms-1.1-spec-1.1.jar
+/usr/share/java/geronimo-jms-1.1-spec.jar
+/usr/share/java/geronimo-jpa-3.0-spec.jar
+/usr/share/java/geronimo-jta-1.0.1b-spec.jar
+/usr/share/java/gnumail.jar
+/usr/share/java/groovy.jar
+/usr/share/java/jamon.jar
+/usr/share/java/javassist.jar
+/usr/share/java/jaxen.jar
+/usr/share/java/jetty.jar
+/usr/share/java/jsp-api-2.1.jar
+/usr/share/java/jug-asl.jar
+/usr/share/java/junit.jar
+/usr/share/java/log4j-1.2.jar
+/usr/share/java/proxool.jar
+/usr/share/java/servlet-api-2.5.jar
+/usr/share/java/slf4j-api.jar
+/usr/share/java/xstream.jar
Added: openjdk-crypto/trunk/debian/build.xml
===================================================================
--- openjdk-crypto/trunk/debian/build.xml (rev 0)
+++ openjdk-crypto/trunk/debian/build.xml 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+
+<project name="pkg-java" default="package" basedir="..">
+
+ <property name="build.sourceDirectory" value="src/main/java"/>
+ <property name="build.resourcesDirectory" value="src/main/resources"/>
+ <property name="build.directory" value="build"/>
+ <property name="build.outputDirectory" value="${build.directory}/classes"/>
+
+ <target name="init">
+ <available property="available.resources" file="${build.resourcesDirectory}"/>
+ </target>
+
+ <target name="clean">
+ <delete dir="${build.directory}"/>
+ </target>
+
+ <target name="process-resources" depends="init" if="available.resources">
+ <mkdir dir="${build.outputDirectory}"/>
+ <copy todir="${build.outputDirectory}">
+ <fileset dir="${build.resourcesDirectory}"/>
+ </copy>
+ </target>
+
+ <target name="compile" depends="process-resources">
+ <mkdir dir="${build.outputDirectory}"/>
+ <javac
+ destdir="${build.outputDirectory}"
+ nowarn="true"
+ source="${sourceVersion}" target="${targetVersion}"
+ debug="on">
+ <src path="${build.sourceDirectory}"/>
+ </javac>
+ </target>
+
+ <target name="package" depends="compile">
+ <jar jarfile="${build.directory}/${artifactId}-${artifactVersion}.jar"
+ basedir="${build.outputDirectory}"/>
+ </target>
+
+</project>
+
Added: openjdk-crypto/trunk/debian/changelog
===================================================================
--- openjdk-crypto/trunk/debian/changelog (rev 0)
+++ openjdk-crypto/trunk/debian/changelog 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,5 @@
+openjdk-crypto (1-1) unstable; urgency=low
+
+ * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
+
+ -- Chris Grzegorczyk <grze at eucalyptus.com> Fri, 12 Mar 2010 18:59:34 -0800
Added: openjdk-crypto/trunk/debian/compat
===================================================================
--- openjdk-crypto/trunk/debian/compat (rev 0)
+++ openjdk-crypto/trunk/debian/compat 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1 @@
+7
Added: openjdk-crypto/trunk/debian/control
===================================================================
--- openjdk-crypto/trunk/debian/control (rev 0)
+++ openjdk-crypto/trunk/debian/control 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,23 @@
+Source: openjdk-crypto
+Section: java
+Priority: optional
+Maintainer: Debian Eucalyptus Maintainers <pkg-eucalyptus-maintainers at lists.alioth.debian.org>
+Uploaders:
+ Chris Grzegorczyk <grze at eucalyptus.com>,
+ Charles Plessy <plessy at debian.org>,
+ Steffen Moeller <plessy at debian.org>,
+ Graziano Obertelli <graziano at eucalyptus.com>,
+ Kyo Lee <kyo.lee at eucalyptus.com>,
+DM-Upload-Allowed: yes
+Build-Depends: ant, debhelper (>= 5), cdbs (>= 0.4.5.3)
+Build-Depends-Indep: default-jdk
+Standards-Version: 3.8.4
+Homepage: https://code.launchpad.net/~openjdk/openjdk/openjdk6
+
+Package: libopenjdk-crypto-java
+Architecture: any
+Depends: ${misc:Depends}, default-jre-headless
+Description: Simplified and unrestricted javax.crypto bootstrap library
+ Provides a simple unrestricted version of the javax.crypto package
+ which can be provided when bootstrapping the Java Virtual Machine. This
+ is needed to load, e.g., unsigned crypo SPI implementations.
Added: openjdk-crypto/trunk/debian/copyright
===================================================================
--- openjdk-crypto/trunk/debian/copyright (rev 0)
+++ openjdk-crypto/trunk/debian/copyright 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,46 @@
+This package was debianized by:
+
+ Chris Grzegorczyk <grze at eucalyptus.com> on Fri, 12 Mar 2010 18:59:34 -0800
+
+Copyright:
+
+ Copyright 1997-2007 Sun Microsystems, Inc.
+
+License:
+
+JCE/Crypto code is distributed under the terms of the GNU General Public
+License with the following clarification and special 'Classpath' exception:
+
+ "CLASSPATH" EXCEPTION TO THE GPL
+
+ Certain source files distributed by Sun Microsystems, Inc. are subject to
+ the following clarification and special exception to the GPL, but only where
+ Sun has expressly included in the particular source file's header the words
+ "Sun designates this particular file as subject to the "Classpath" exception
+ as provided by Sun in the LICENSE file that accompanied this code."
+
+ Linking this library statically or dynamically with other modules is making
+ a combined work based on this library. Thus, the terms and conditions of
+ the GNU General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent modules,
+ and to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent module,
+ the terms and conditions of the license of that module. An independent
+ module is a module which is not derived from or based on this library.
+ If you modify this library, you may extend this exception to your version
+ of the library, but you are not obligated to do so. If you do not wish to
+ do so, delete this exception statement from your version.
+
+ On Debian GNU/Linux system you can find a copy of the GPL in
+ `/usr/share/common-licenses/GPL-2'.
+
+The Debian packaging is:
+
+ Copyright (C) 2010 Chris Grzegorczyk <grze at eucalyptus.com>
+
+and is licensed under the BSD license,
+see `/usr/share/common-licenses/BSD'.
+
Added: openjdk-crypto/trunk/debian/rules
===================================================================
--- openjdk-crypto/trunk/debian/rules (rev 0)
+++ openjdk-crypto/trunk/debian/rules 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,18 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/ant.mk
+include /usr/share/cdbs/1/rules/simple-patchsys.mk
+
+JAVA_HOME := /usr/lib/jvm/default-java
+REQUIRED_JVM_VERSION := 1.5
+DEB_ANT_BUILDFILE := debian/build.xml
+DEB_ANT_ARGS := -DartifactVersion=$(DEB_UPSTREAM_VERSION) \
+ -DartifactId=$(DEB_SOURCE_PACKAGE) \
+ -DsourceVersion=$(REQUIRED_JVM_VERSION) \
+ -DtargetVersion=$(REQUIRED_JVM_VERSION)
+
+binary-post-install/lib$(DEB_SOURCE_PACKAGE)-java::
+ dh_install -plib$(DEB_SOURCE_PACKAGE)-java build/$(DEB_SOURCE_PACKAGE)-$(DEB_UPSTREAM_VERSION).jar usr/share/java
+ dh_link -plib$(DEB_SOURCE_PACKAGE)-java usr/share/java/$(DEB_SOURCE_PACKAGE)-$(DEB_UPSTREAM_VERSION).jar usr/share/java/$(DEB_SOURCE_PACKAGE).jar
+
Property changes on: openjdk-crypto/trunk/debian/rules
___________________________________________________________________
Added: svn:executable
+ *
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/BadPaddingException.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/BadPaddingException.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/BadPaddingException.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This exception is thrown when a particular padding mechanism is
+ * expected for the input data but the data is not padded properly.
+ *
+ * @author Gigi Ankney
+ * @since 1.4
+ */
+
+public class BadPaddingException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -5315033893984728443L;
+
+ /**
+ * Constructs a BadPaddingException with no detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ */
+ public BadPaddingException() {
+ super();
+ }
+
+ /**
+ * Constructs a BadPaddingException with the specified
+ * detail message.
+ *
+ * @param msg the detail message.
+ */
+ public BadPaddingException(String msg) {
+ super(msg);
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/Cipher.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/Cipher.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/Cipher.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,2258 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.util.*;
+import java.util.regex.*;
+
+import static java.util.Locale.ENGLISH;
+
+import java.security.*;
+import java.security.Provider.Service;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import javax.crypto.spec.*;
+
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+
+import sun.security.util.Debug;
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class provides the functionality of a cryptographic cipher for
+ * encryption and decryption. It forms the core of the Java Cryptographic
+ * Extension (JCE) framework.
+ *
+ * <p>In order to create a Cipher object, the application calls the
+ * Cipher's <code>getInstance</code> method, and passes the name of the
+ * requested <i>transformation</i> to it. Optionally, the name of a provider
+ * may be specified.
+ *
+ * <p>A <i>transformation</i> is a string that describes the operation (or
+ * set of operations) to be performed on the given input, to produce some
+ * output. A transformation always includes the name of a cryptographic
+ * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
+ * padding scheme.
+ *
+ * <p> A transformation is of the form:<p>
+ *
+ * <ul>
+ * <li>"<i>algorithm/mode/padding</i>" or
+ * <p>
+ * <li>"<i>algorithm</i>"
+ * </ul>
+ *
+ * <P> (in the latter case,
+ * provider-specific default values for the mode and padding scheme are used).
+ * For example, the following is a valid transformation:<p>
+ *
+ * <pre>
+ * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
+ * </pre>
+ *
+ * Using modes such as <code>CFB</code> and <code>OFB<code>, block
+ * ciphers can encrypt data in units smaller than the cipher's actual
+ * block size. When requesting such a mode, you may optionally specify
+ * the number of bits to be processed at a time by appending this number
+ * to the mode name as shown in the "<code>DES/CFB8/NoPadding</code>" and
+ * "<code>DES/OFB32/PKCS5Padding</code>" transformations. If no such
+ * number is specified, a provider-specific default is used. (For
+ * example, the SunJCE provider uses a default of 64 bits for DES.)
+ * Thus, block ciphers can be turned into byte-oriented stream ciphers by
+ * using an 8 bit mode such as CFB8 or OFB8.
+ *
+ * @author Jan Luehe
+ * @see KeyGenerator
+ * @see SecretKey
+ * @since 1.4
+ */
+
+public class Cipher {
+
+ private static final Debug debug =
+ Debug.getInstance("jca", "Cipher");
+
+ /**
+ * Constant used to initialize cipher to encryption mode.
+ */
+ public static final int ENCRYPT_MODE = 1;
+
+ /**
+ * Constant used to initialize cipher to decryption mode.
+ */
+ public static final int DECRYPT_MODE = 2;
+
+ /**
+ * Constant used to initialize cipher to key-wrapping mode.
+ */
+ public static final int WRAP_MODE = 3;
+
+ /**
+ * Constant used to initialize cipher to key-unwrapping mode.
+ */
+ public static final int UNWRAP_MODE = 4;
+
+ /**
+ * Constant used to indicate the to-be-unwrapped key is a "public key".
+ */
+ public static final int PUBLIC_KEY = 1;
+
+ /**
+ * Constant used to indicate the to-be-unwrapped key is a "private key".
+ */
+ public static final int PRIVATE_KEY = 2;
+
+ /**
+ * Constant used to indicate the to-be-unwrapped key is a "secret key".
+ */
+ public static final int SECRET_KEY = 3;
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation (delegate)
+ private CipherSpi spi;
+
+ // The transformation
+ private String transformation;
+
+ // The exemption mechanism that needs to be enforced
+ private ExemptionMechanism exmech;
+
+ // Flag which indicates whether or not this cipher has been initialized
+ private boolean initialized = false;
+
+ // The operation mode - store the operation mode after the
+ // cipher has been initialized.
+ private int opmode = 0;
+
+ // The OID for the KeyUsage extension in an X.509 v3 certificate
+ private static final String KEY_USAGE_EXTENSION_OID = "2.5.29.15";
+
+ // next SPI to try in provider selection
+ // null once provider is selected
+ private CipherSpi firstSpi;
+
+ // next service to try in provider selection
+ // null once provider is selected
+ private Service firstService;
+
+ // remaining services to try in provider selection
+ // null once provider is selected
+ private Iterator serviceIterator;
+
+ // list of transform Strings to lookup in the provider
+ private List transforms;
+
+ private final Object lock;
+
+ /**
+ * Creates a Cipher object.
+ *
+ * @param cipherSpi the delegate
+ * @param provider the provider
+ * @param transformation the transformation
+ */
+ protected Cipher(CipherSpi cipherSpi,
+ Provider provider,
+ String transformation) {
+ this.spi = cipherSpi;
+ this.provider = provider;
+ this.transformation = transformation;
+ this.lock = null;
+ }
+
+ /**
+ * Creates a Cipher object. Called internally and by NullCipher.
+ *
+ * @param cipherSpi the delegate
+ * @param transformation the transformation
+ */
+ Cipher(CipherSpi cipherSpi, String transformation) {
+ this.spi = cipherSpi;
+ this.transformation = transformation;
+ this.lock = null;
+ }
+
+ private Cipher(CipherSpi firstSpi, Service firstService,
+ Iterator serviceIterator, String transformation, List transforms) {
+ this.firstSpi = firstSpi;
+ this.firstService = firstService;
+ this.serviceIterator = serviceIterator;
+ this.transforms = transforms;
+ this.transformation = transformation;
+ this.lock = new Object();
+ }
+
+ private static String[] tokenizeTransformation(String transformation)
+ throws NoSuchAlgorithmException {
+ if (transformation == null) {
+ throw new NoSuchAlgorithmException("No transformation given");
+ }
+ /*
+ * array containing the components of a Cipher transformation:
+ *
+ * index 0: algorithm component (e.g., DES)
+ * index 1: feedback component (e.g., CFB)
+ * index 2: padding component (e.g., PKCS5Padding)
+ */
+ String[] parts = new String[3];
+ int count = 0;
+ StringTokenizer parser = new StringTokenizer(transformation, "/");
+ try {
+ while (parser.hasMoreTokens() && count < 3) {
+ parts[count++] = parser.nextToken().trim();
+ }
+ if (count == 0 || count == 2 || parser.hasMoreTokens()) {
+ throw new NoSuchAlgorithmException("Invalid transformation"
+ + " format:" +
+ transformation);
+ }
+ } catch (NoSuchElementException e) {
+ throw new NoSuchAlgorithmException("Invalid transformation " +
+ "format:" + transformation);
+ }
+ if ((parts[0] == null) || (parts[0].length() == 0)) {
+ throw new NoSuchAlgorithmException("Invalid transformation:" +
+ "algorithm not specified-"
+ + transformation);
+ }
+ return parts;
+ }
+
+ // Provider attribute name for supported chaining mode
+ private final static String ATTR_MODE = "SupportedModes";
+ // Provider attribute name for supported padding names
+ private final static String ATTR_PAD = "SupportedPaddings";
+
+ // constants indicating whether the provider supports
+ // a given mode or padding
+ private final static int S_NO = 0; // does not support
+ private final static int S_MAYBE = 1; // unable to determine
+ private final static int S_YES = 2; // does support
+
+ /**
+ * Nested class to deal with modes and paddings.
+ */
+ private static class Transform {
+ // transform string to lookup in the provider
+ final String transform;
+ // the mode/padding suffix in upper case. for example, if the algorithm
+ // to lookup is "DES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING"
+ // if loopup is "DES", suffix is the empty string
+ // needed because aliases prevent straight transform.equals()
+ final String suffix;
+ // value to pass to setMode() or null if no such call required
+ final String mode;
+ // value to pass to setPadding() or null if no such call required
+ final String pad;
+ Transform(String alg, String suffix, String mode, String pad) {
+ this.transform = alg + suffix;
+ this.suffix = suffix.toUpperCase(Locale.ENGLISH);
+ this.mode = mode;
+ this.pad = pad;
+ }
+ // set mode and padding for the given SPI
+ void setModePadding(CipherSpi spi) throws NoSuchAlgorithmException,
+ NoSuchPaddingException {
+ if (mode != null) {
+ spi.engineSetMode(mode);
+ }
+ if (pad != null) {
+ spi.engineSetPadding(pad);
+ }
+ }
+ // check whether the given services supports the mode and
+ // padding described by this Transform
+ int supportsModePadding(Service s) {
+ int smode = supportsMode(s);
+ if (smode == S_NO) {
+ return smode;
+ }
+ int spad = supportsPadding(s);
+ // our constants are defined so that Math.min() is a tri-valued AND
+ return Math.min(smode, spad);
+ }
+
+ // separate methods for mode and padding
+ // called directly by Cipher only to throw the correct exception
+ int supportsMode(Service s) {
+ return supports(s, ATTR_MODE, mode);
+ }
+ int supportsPadding(Service s) {
+ return supports(s, ATTR_PAD, pad);
+ }
+
+ private static int supports(Service s, String attrName, String value) {
+ if (value == null) {
+ return S_YES;
+ }
+ String regexp = s.getAttribute(attrName);
+ if (regexp == null) {
+ return S_MAYBE;
+ }
+ return matches(regexp, value) ? S_YES : S_NO;
+ }
+
+ // Map<String,Pattern> for previously compiled patterns
+ // XXX use ConcurrentHashMap once available
+ private final static Map patternCache =
+ Collections.synchronizedMap(new HashMap());
+
+ private static boolean matches(String regexp, String str) {
+ Pattern pattern = (Pattern)patternCache.get(regexp);
+ if (pattern == null) {
+ pattern = Pattern.compile(regexp);
+ patternCache.put(regexp, pattern);
+ }
+ return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches();
+ }
+
+ }
+
+ private static List getTransforms(String transformation)
+ throws NoSuchAlgorithmException {
+ String[] parts = tokenizeTransformation(transformation);
+
+ String alg = parts[0];
+ String mode = parts[1];
+ String pad = parts[2];
+ if ((mode != null) && (mode.length() == 0)) {
+ mode = null;
+ }
+ if ((pad != null) && (pad.length() == 0)) {
+ pad = null;
+ }
+
+ if ((mode == null) && (pad == null)) {
+ // DES
+ Transform tr = new Transform(alg, "", null, null);
+ return Collections.singletonList(tr);
+ } else { // if ((mode != null) && (pad != null)) {
+ // DES/CBC/PKCS5Padding
+ List list = new ArrayList(4);
+ list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
+ list.add(new Transform(alg, "/" + mode, null, pad));
+ list.add(new Transform(alg, "//" + pad, mode, null));
+ list.add(new Transform(alg, "", mode, pad));
+ return list;
+ }
+ }
+
+ // get the transform matching the specified service
+ private static Transform getTransform(Service s, List transforms) {
+ String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH);
+ for (Iterator t = transforms.iterator(); t.hasNext(); ) {
+ Transform tr = (Transform)t.next();
+ if (alg.endsWith(tr.suffix)) {
+ return tr;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a <code>Cipher</code> object that implements the specified
+ * transformation.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new Cipher object encapsulating the
+ * CipherSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param transformation the name of the transformation, e.g.,
+ * <i>DES/CBC/PKCS5Padding</i>.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard transformation names.
+ *
+ * @return a cipher that implements the requested transformation.
+ *
+ * @exception NoSuchAlgorithmException if <code>transformation</code>
+ * is null, empty, in an invalid format,
+ * or if no Provider supports a CipherSpi implementation for the
+ * specified algorithm.
+ *
+ * @exception NoSuchPaddingException if <code>transformation</code>
+ * contains a padding scheme that is not available.
+ *
+ * @see java.security.Provider
+ */
+ public static final Cipher getInstance(String transformation)
+ throws NoSuchAlgorithmException, NoSuchPaddingException
+ {
+ List transforms = getTransforms(transformation);
+ List cipherServices = new ArrayList(transforms.size());
+ for (Iterator t = transforms.iterator(); t.hasNext(); ) {
+ Transform transform = (Transform)t.next();
+ cipherServices.add(new ServiceId("Cipher", transform.transform));
+ }
+ List services = GetInstance.getServices(cipherServices);
+ // make sure there is at least one service from a signed provider
+ // and that it can use the specified mode and padding
+ Iterator t = services.iterator();
+ Exception failure = null;
+ while (t.hasNext()) {
+ Service s = (Service)t.next();
+ Transform tr = getTransform(s, transforms);
+ if (tr == null) {
+ // should never happen
+ continue;
+ }
+ int canuse = tr.supportsModePadding(s);
+ if (canuse == S_NO) {
+ // does not support mode or padding we need, ignore
+ continue;
+ }
+ if (canuse == S_YES) {
+ return new Cipher(null, s, t, transformation, transforms);
+ } else { // S_MAYBE, try out if it works
+ try {
+ CipherSpi spi = (CipherSpi)s.newInstance(null);
+ tr.setModePadding(spi);
+ return new Cipher(spi, s, t, transformation, transforms);
+ } catch (Exception e) {
+ failure = e;
+ }
+ }
+ }
+ throw new NoSuchAlgorithmException
+ ("Cannot find any provider supporting " + transformation, failure);
+ }
+
+ /**
+ * Returns a <code>Cipher</code> object that implements the specified
+ * transformation.
+ *
+ * <p> A new Cipher object encapsulating the
+ * CipherSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param transformation the name of the transformation,
+ * e.g., <i>DES/CBC/PKCS5Padding</i>.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard transformation names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return a cipher that implements the requested transformation.
+ *
+ * @exception NoSuchAlgorithmException if <code>transformation</code>
+ * is null, empty, in an invalid format,
+ * or if a CipherSpi implementation for the specified algorithm
+ * is not available from the specified provider.
+ *
+ * @exception NoSuchProviderException if the specified provider is not
+ * registered in the security provider list.
+ *
+ * @exception NoSuchPaddingException if <code>transformation</code>
+ * contains a padding scheme that is not available.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static final Cipher getInstance(String transformation,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ NoSuchPaddingException
+ {
+ if ((provider == null) || (provider.length() == 0)) {
+ throw new IllegalArgumentException("Missing provider");
+ }
+ Provider p = Security.getProvider(provider);
+ if (p == null) {
+ throw new NoSuchProviderException("No such provider: " +
+ provider);
+ }
+ return getInstance(transformation, p);
+ }
+
+ /**
+ * Returns a <code>Cipher</code> object that implements the specified
+ * transformation.
+ *
+ * <p> A new Cipher object encapsulating the
+ * CipherSpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * @param transformation the name of the transformation,
+ * e.g., <i>DES/CBC/PKCS5Padding</i>.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard transformation names.
+ *
+ * @param provider the provider.
+ *
+ * @return a cipher that implements the requested transformation.
+ *
+ * @exception NoSuchAlgorithmException if <code>transformation</code>
+ * is null, empty, in an invalid format,
+ * or if a CipherSpi implementation for the specified algorithm
+ * is not available from the specified Provider object.
+ *
+ * @exception NoSuchPaddingException if <code>transformation</code>
+ * contains a padding scheme that is not available.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null.
+ *
+ * @see java.security.Provider
+ */
+ public static final Cipher getInstance(String transformation,
+ Provider provider)
+ throws NoSuchAlgorithmException, NoSuchPaddingException
+ {
+ if (provider == null) {
+ throw new IllegalArgumentException("Missing provider");
+ }
+ Exception failure = null;
+ List transforms = getTransforms(transformation);
+ String paddingError = null;
+ for (Iterator t = transforms.iterator(); t.hasNext();) {
+ Transform tr = (Transform)t.next();
+ Service s = provider.getService("Cipher", tr.transform);
+ if (s == null) {
+ continue;
+ }
+ if (tr.supportsMode(s) == S_NO) {
+ continue;
+ }
+ if (tr.supportsPadding(s) == S_NO) {
+ paddingError = tr.pad;
+ continue;
+ }
+ try {
+ CipherSpi spi = (CipherSpi)s.newInstance(null);
+ tr.setModePadding(spi);
+ Cipher cipher = new Cipher(spi, transformation);
+ cipher.provider = s.getProvider();
+ return cipher;
+ } catch (Exception e) {
+ failure = e;
+ }
+ }
+
+ // throw NoSuchPaddingException if the problem is with padding
+ if (failure instanceof NoSuchPaddingException) {
+ throw (NoSuchPaddingException)failure;
+ }
+ if (paddingError != null) {
+ throw new NoSuchPaddingException
+ ("Padding not supported: " + paddingError);
+ }
+ throw new NoSuchAlgorithmException
+ ("No such algorithm: " + transformation, failure);
+ }
+
+ // max number of debug warnings to print from chooseFirstProvider()
+ private static int warnCount = 10;
+
+ /**
+ * Choose the Spi from the first provider available. Used if
+ * delayed provider selection is not possible because init()
+ * is not the first method called.
+ */
+ void chooseFirstProvider() {
+ if (spi != null) {
+ return;
+ }
+ synchronized (lock) {
+ if (spi != null) {
+ return;
+ }
+ if (debug != null) {
+ int w = --warnCount;
+ if (w >= 0) {
+ debug.println("Cipher.init() not first method "
+ + "called, disabling delayed provider selection");
+ if (w == 0) {
+ debug.println("Further warnings of this type will "
+ + "be suppressed");
+ }
+ new Exception("Call trace").printStackTrace();
+ }
+ }
+ Exception lastException = null;
+ while ((firstService != null) || serviceIterator.hasNext()) {
+ Service s;
+ CipherSpi thisSpi;
+ if (firstService != null) {
+ s = firstService;
+ thisSpi = firstSpi;
+ firstService = null;
+ firstSpi = null;
+ } else {
+ s = (Service)serviceIterator.next();
+ thisSpi = null;
+ }
+ Transform tr = getTransform(s, transforms);
+ if (tr == null) {
+ // should never happen
+ continue;
+ }
+ if (tr.supportsModePadding(s) == S_NO) {
+ continue;
+ }
+ try {
+ if (thisSpi == null) {
+ Object obj = s.newInstance(null);
+ if (obj instanceof CipherSpi == false) {
+ continue;
+ }
+ thisSpi = (CipherSpi)obj;
+ }
+ tr.setModePadding(thisSpi);
+ spi = thisSpi;
+ provider = s.getProvider();
+ // not needed any more
+ firstService = null;
+ serviceIterator = null;
+ transforms = null;
+ return;
+ } catch (Exception e) {
+ lastException = e;
+ }
+ }
+ ProviderException e = new ProviderException
+ ("Could not construct CipherSpi instance");
+ if (lastException != null) {
+ e.initCause(lastException);
+ }
+ throw e;
+ }
+ }
+
+ private final static int I_KEY = 1;
+ private final static int I_PARAMSPEC = 2;
+ private final static int I_PARAMS = 3;
+ private final static int I_CERT = 4;
+
+ private void implInit(CipherSpi thisSpi, int type, int opmode, Key key,
+ AlgorithmParameterSpec paramSpec, AlgorithmParameters params,
+ SecureRandom random) throws InvalidKeyException,
+ InvalidAlgorithmParameterException {
+ switch (type) {
+ case I_KEY:
+ thisSpi.engineInit(opmode, key, random);
+ break;
+ case I_PARAMSPEC:
+ thisSpi.engineInit(opmode, key, paramSpec, random);
+ break;
+ case I_PARAMS:
+ thisSpi.engineInit(opmode, key, params, random);
+ break;
+ case I_CERT:
+ thisSpi.engineInit(opmode, key, random);
+ break;
+ default:
+ throw new AssertionError("Internal Cipher error: " + type);
+ }
+ }
+
+ private void chooseProvider(int initType, int opmode, Key key,
+ AlgorithmParameterSpec paramSpec,
+ AlgorithmParameters params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ synchronized (lock) {
+ if (spi != null) {
+ implInit(spi, initType, opmode, key, paramSpec, params, random);
+ return;
+ }
+ Exception lastException = null;
+ while ((firstService != null) || serviceIterator.hasNext()) {
+ Service s;
+ CipherSpi thisSpi;
+ if (firstService != null) {
+ s = firstService;
+ thisSpi = firstSpi;
+ firstService = null;
+ firstSpi = null;
+ } else {
+ s = (Service)serviceIterator.next();
+ thisSpi = null;
+ }
+ // if provider says it does not support this key, ignore it
+ if (s.supportsParameter(key) == false) {
+ continue;
+ }
+ Transform tr = getTransform(s, transforms);
+ if (tr == null) {
+ // should never happen
+ continue;
+ }
+ if (tr.supportsModePadding(s) == S_NO) {
+ continue;
+ }
+ try {
+ if (thisSpi == null) {
+ thisSpi = (CipherSpi)s.newInstance(null);
+ }
+ tr.setModePadding(thisSpi);
+ implInit(thisSpi, initType, opmode, key, paramSpec,
+ params, random);
+ provider = s.getProvider();
+ this.spi = thisSpi;
+ firstService = null;
+ serviceIterator = null;
+ transforms = null;
+ return;
+ } catch (Exception e) {
+ // NoSuchAlgorithmException from newInstance()
+ // InvalidKeyException from init()
+ // RuntimeException (ProviderException) from init()
+ // SecurityException from crypto permission check
+ if (lastException == null) {
+ lastException = e;
+ }
+ }
+ }
+ // no working provider found, fail
+ if (lastException instanceof InvalidKeyException) {
+ throw (InvalidKeyException)lastException;
+ }
+ if (lastException instanceof InvalidAlgorithmParameterException) {
+ throw (InvalidAlgorithmParameterException)lastException;
+ }
+ if (lastException instanceof RuntimeException) {
+ throw (RuntimeException)lastException;
+ }
+ String kName = (key != null) ? key.getClass().getName() : "(null)";
+ throw new InvalidKeyException
+ ("No installed provider supports this key: "
+ + kName, lastException);
+ }
+ }
+
+ /**
+ * Returns the provider of this <code>Cipher</code> object.
+ *
+ * @return the provider of this <code>Cipher</code> object
+ */
+ public final Provider getProvider() {
+ chooseFirstProvider();
+ return this.provider;
+ }
+
+ /**
+ * Returns the algorithm name of this <code>Cipher</code> object.
+ *
+ * <p>This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this <code>Cipher</code>
+ * object..
+ *
+ * @return the algorithm name of this <code>Cipher</code> object.
+ */
+ public final String getAlgorithm() {
+ return this.transformation;
+ }
+
+ /**
+ * Returns the block size (in bytes).
+ *
+ * @return the block size (in bytes), or 0 if the underlying algorithm is
+ * not a block cipher
+ */
+ public final int getBlockSize() {
+ chooseFirstProvider();
+ return spi.engineGetBlockSize();
+ }
+
+ /**
+ * Returns the length in bytes that an output buffer would need to be in
+ * order to hold the result of the next <code>update</code> or
+ * <code>doFinal</code> operation, given the input length
+ * <code>inputLen</code> (in bytes).
+ *
+ * <p>This call takes into account any unprocessed (buffered) data from a
+ * previous <code>update</code> call, and padding.
+ *
+ * <p>The actual output length of the next <code>update</code> or
+ * <code>doFinal</code> call may be smaller than the length returned by
+ * this method.
+ *
+ * @param inputLen the input length (in bytes)
+ *
+ * @return the required output buffer size (in bytes)
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not yet been initialized)
+ */
+ public final int getOutputSize(int inputLen) {
+
+ if (!initialized && !(this instanceof NullCipher)) {
+ throw new IllegalStateException("Cipher not initialized");
+ }
+ if (inputLen < 0) {
+ throw new IllegalArgumentException("Input size must be equal " +
+ "to or greater than zero");
+ }
+ chooseFirstProvider();
+ return spi.engineGetOutputSize(inputLen);
+ }
+
+ /**
+ * Returns the initialization vector (IV) in a new buffer.
+ *
+ * <p>This is useful in the case where a random IV was created,
+ * or in the context of password-based encryption or
+ * decryption, where the IV is derived from a user-supplied password.
+ *
+ * @return the initialization vector in a new buffer, or null if the
+ * underlying algorithm does not use an IV, or if the IV has not yet
+ * been set.
+ */
+ public final byte[] getIV() {
+ chooseFirstProvider();
+ return spi.engineGetIV();
+ }
+
+ /**
+ * Returns the parameters used with this cipher.
+ *
+ * <p>The returned parameters may be the same that were used to initialize
+ * this cipher, or may contain a combination of default and random
+ * parameter values used by the underlying cipher implementation if this
+ * cipher requires algorithm parameters but was not initialized with any.
+ *
+ * @return the parameters used with this cipher, or null if this cipher
+ * does not use any parameters.
+ */
+ public final AlgorithmParameters getParameters() {
+ chooseFirstProvider();
+ return spi.engineGetParameters();
+ }
+
+ /**
+ * Returns the exemption mechanism object used with this cipher.
+ *
+ * @return the exemption mechanism object used with this cipher, or
+ * null if this cipher does not use any exemption mechanism.
+ */
+ public final ExemptionMechanism getExemptionMechanism() {
+ chooseFirstProvider();
+ return exmech;
+ }
+
+ // check if opmode is one of the defined constants
+ // throw InvalidParameterExeption if not
+ private static void checkOpmode(int opmode) {
+ if ((opmode < ENCRYPT_MODE) || (opmode > UNWRAP_MODE)) {
+ throw new InvalidParameterException("Invalid operation mode");
+ }
+ }
+
+ /**
+ * Initializes this cipher with a key.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters that cannot be
+ * derived from the given <code>key</code>, the underlying cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidKeyException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #getParameters() getParameters} or
+ * {@link #getIV() getIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them using the {@link SecureRandom <code>SecureRandom</code>}
+ * implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of
+ * the following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the key
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or if this cipher is being initialized for
+ * decryption and requires algorithm parameters that cannot be
+ * determined from the given key, or if the given key has a keysize that
+ * exceeds the maximum allowable keysize (as determined from the
+ * configured jurisdiction policy files).
+ */
+ public final void init(int opmode, Key key) throws InvalidKeyException {
+ init(opmode, key, JceSecurity.RANDOM);
+ }
+
+ /**
+ * Initializes this cipher with a key and a source of randomness.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters that cannot be
+ * derived from the given <code>key</code>, the underlying cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidKeyException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #getParameters() getParameters} or
+ * {@link #getIV() getIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or if this cipher is being initialized for
+ * decryption and requires algorithm parameters that cannot be
+ * determined from the given key, or if the given key has a keysize that
+ * exceeds the maximum allowable keysize (as determined from the
+ * configured jurisdiction policy files).
+ */
+ public final void init(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException
+ {
+ initialized = false;
+ checkOpmode(opmode);
+
+ if (spi != null) {
+ spi.engineInit(opmode, key, random);
+ } else {
+ try {
+ chooseProvider(I_KEY, opmode, key, null, null, random);
+ } catch (InvalidAlgorithmParameterException e) {
+ // should never occur
+ throw new InvalidKeyException(e);
+ }
+ }
+
+ initialized = true;
+ this.opmode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with a key and a set of algorithm
+ * parameters.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #getParameters() getParameters} or
+ * {@link #getIV() getIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them using the {@link SecureRandom <code>SecureRandom</code>}
+ * implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or its keysize exceeds the maximum allowable
+ * keysize (as determined from the configured jurisdiction policy files).
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null, or the given
+ * algorithm parameters imply a cryptographic strength that would exceed
+ * the legal limits (as determined from the configured jurisdiction
+ * policy files).
+ */
+ public final void init(int opmode, Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ init(opmode, key, params, JceSecurity.RANDOM);
+ }
+
+ /**
+ * Initializes this cipher with a key, a set of algorithm
+ * parameters, and a source of randomness.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #getParameters() getParameters} or
+ * {@link #getIV() getIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or its keysize exceeds the maximum allowable
+ * keysize (as determined from the configured jurisdiction policy files).
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null, or the given
+ * algorithm parameters imply a cryptographic strength that would exceed
+ * the legal limits (as determined from the configured jurisdiction
+ * policy files).
+ */
+ public final void init(int opmode, Key key, AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ initialized = false;
+ checkOpmode(opmode);
+
+ if (spi != null) {
+ spi.engineInit(opmode, key, params, random);
+ } else {
+ chooseProvider(I_PARAMSPEC, opmode, key, params, null, random);
+ }
+
+ initialized = true;
+ this.opmode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with a key and a set of algorithm
+ * parameters.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #getParameters() getParameters} or
+ * {@link #getIV() getIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them using the {@link SecureRandom <code>SecureRandom</code>}
+ * implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following: <code>ENCRYPT_MODE</code>,
+ * <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code>
+ * or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or its keysize exceeds the maximum allowable
+ * keysize (as determined from the configured jurisdiction policy files).
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null, or the given
+ * algorithm parameters imply a cryptographic strength that would exceed
+ * the legal limits (as determined from the configured jurisdiction
+ * policy files).
+ */
+ public final void init(int opmode, Key key, AlgorithmParameters params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ init(opmode, key, params, JceSecurity.RANDOM);
+ }
+
+ /**
+ * Initializes this cipher with a key, a set of algorithm
+ * parameters, and a source of randomness.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #getParameters() getParameters} or
+ * {@link #getIV() getIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following: <code>ENCRYPT_MODE</code>,
+ * <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code>
+ * or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or its keysize exceeds the maximum allowable
+ * keysize (as determined from the configured jurisdiction policy files).
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null, or the given
+ * algorithm parameters imply a cryptographic strength that would exceed
+ * the legal limits (as determined from the configured jurisdiction
+ * policy files).
+ */
+ public final void init(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ initialized = false;
+ checkOpmode(opmode);
+
+ if (spi != null) {
+ spi.engineInit(opmode, key, params, random);
+ } else {
+ chooseProvider(I_PARAMS, opmode, key, null, params, random);
+ }
+
+ initialized = true;
+ this.opmode = opmode;
+ }
+
+ /**
+ * Initializes this cipher with the public key from the given certificate.
+ * <p> The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending
+ * on the value of <code>opmode</code>.
+ *
+ * <p>If the certificate is of type X.509 and has a <i>key usage</i>
+ * extension field marked as critical, and the value of the <i>key usage</i>
+ * extension field implies that the public key in
+ * the certificate and its corresponding private key are not
+ * supposed to be used for the operation represented by the value
+ * of <code>opmode</code>,
+ * an <code>InvalidKeyException</code>
+ * is thrown.
+ *
+ * <p> If this cipher requires any algorithm parameters that cannot be
+ * derived from the public key in the given certificate, the underlying
+ * cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or ramdom values) if it is being
+ * initialized for encryption or key wrapping, and raise an <code>
+ * InvalidKeyException</code> if it is being initialized for decryption or
+ * key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #getParameters() getParameters} or
+ * {@link #getIV() getIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them using the
+ * <code>SecureRandom</code>
+ * implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param certificate the certificate
+ *
+ * @exception InvalidKeyException if the public key in the given
+ * certificate is inappropriate for initializing this cipher, or this
+ * cipher is being initialized for decryption or unwrapping keys and
+ * requires algorithm parameters that cannot be determined from the
+ * public key in the given certificate, or the keysize of the public key
+ * in the given certificate has a keysize that exceeds the maximum
+ * allowable keysize (as determined by the configured jurisdiction policy
+ * files).
+ */
+ public final void init(int opmode, Certificate certificate)
+ throws InvalidKeyException
+ {
+ init(opmode, certificate, JceSecurity.RANDOM);
+ }
+
+ /**
+ * Initializes this cipher with the public key from the given certificate
+ * and
+ * a source of randomness.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping
+ * or key unwrapping, depending on
+ * the value of <code>opmode</code>.
+ *
+ * <p>If the certificate is of type X.509 and has a <i>key usage</i>
+ * extension field marked as critical, and the value of the <i>key usage</i>
+ * extension field implies that the public key in
+ * the certificate and its corresponding private key are not
+ * supposed to be used for the operation represented by the value of
+ * <code>opmode</code>,
+ * an <code>InvalidKeyException</code>
+ * is thrown.
+ *
+ * <p>If this cipher requires any algorithm parameters that cannot be
+ * derived from the public key in the given <code>certificate</code>,
+ * the underlying cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidKeyException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #getParameters() getParameters} or
+ * {@link #getIV() getIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of the
+ * following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param certificate the certificate
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the public key in the given
+ * certificate is inappropriate for initializing this cipher, or this
+ * cipher is being initialized for decryption or unwrapping keys and
+ * requires algorithm parameters that cannot be determined from the
+ * public key in the given certificate, or the keysize of the public key
+ * in the given certificate has a keysize that exceeds the maximum
+ * allowable keysize (as determined by the configured jurisdiction policy
+ * files).
+ */
+ public final void init(int opmode, Certificate certificate,
+ SecureRandom random)
+ throws InvalidKeyException
+ {
+ initialized = false;
+ checkOpmode(opmode);
+
+ // Check key usage if the certificate is of
+ // type X.509.
+ if (certificate instanceof java.security.cert.X509Certificate) {
+ // Check whether the cert has a key usage extension
+ // marked as a critical extension.
+ X509Certificate cert = (X509Certificate)certificate;
+ Set critSet = cert.getCriticalExtensionOIDs();
+
+ if (critSet != null && !critSet.isEmpty()
+ && critSet.contains(KEY_USAGE_EXTENSION_OID)) {
+ boolean[] keyUsageInfo = cert.getKeyUsage();
+ // keyUsageInfo[2] is for keyEncipherment;
+ // keyUsageInfo[3] is for dataEncipherment.
+ if ((keyUsageInfo != null) &&
+ (((opmode == Cipher.ENCRYPT_MODE) &&
+ (keyUsageInfo.length > 3) &&
+ (keyUsageInfo[3] == false)) ||
+ ((opmode == Cipher.WRAP_MODE) &&
+ (keyUsageInfo.length > 2) &&
+ (keyUsageInfo[2] == false)))) {
+ throw new InvalidKeyException("Wrong key usage");
+ }
+ }
+ }
+
+ PublicKey publicKey =
+ (certificate==null? null:certificate.getPublicKey());
+
+ if (spi != null) {
+ spi.engineInit(opmode, publicKey, random);
+ } else {
+ try {
+ chooseProvider(I_CERT, opmode, publicKey, null, null, random);
+ } catch (InvalidAlgorithmParameterException e) {
+ // should never occur
+ throw new InvalidKeyException(e);
+ }
+ }
+
+ initialized = true;
+ this.opmode = opmode;
+ }
+
+ /**
+ * Ensures that Cipher is in a valid state for update() and doFinal()
+ * calls - should be initialized and in ENCRYPT_MODE or DECRYPT_MODE.
+ * @throws IllegalStateException if Cipher object is not in valid state.
+ */
+ private void checkCipherState() {
+ if (!(this instanceof NullCipher)) {
+ if (!initialized) {
+ throw new IllegalStateException("Cipher not initialized");
+ }
+ if ((opmode != Cipher.ENCRYPT_MODE) &&
+ (opmode != Cipher.DECRYPT_MODE)) {
+ throw new IllegalStateException("Cipher not initialized " +
+ "for encryption/decryption");
+ }
+ }
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>The bytes in the <code>input</code> buffer are processed, and the
+ * result is stored in a new buffer.
+ *
+ * <p>If <code>input</code> has a length of zero, this method returns
+ * <code>null</code>.
+ *
+ * @param input the input buffer
+ *
+ * @return the new buffer with the result, or null if the underlying
+ * cipher is a block cipher and the input data is too short to result in a
+ * new block.
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ */
+ public final byte[] update(byte[] input) {
+ checkCipherState();
+
+ // Input sanity check
+ if (input == null) {
+ throw new IllegalArgumentException("Null input buffer");
+ }
+
+ chooseFirstProvider();
+ if (input.length == 0) {
+ return null;
+ }
+ return spi.engineUpdate(input, 0, input.length);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
+ * and the result is stored in a new buffer.
+ *
+ * <p>If <code>inputLen</code> is zero, this method returns
+ * <code>null</code>.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ *
+ * @return the new buffer with the result, or null if the underlying
+ * cipher is a block cipher and the input data is too short to result in a
+ * new block.
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ */
+ public final byte[] update(byte[] input, int inputOffset, int inputLen) {
+ checkCipherState();
+
+ // Input sanity check
+ if (input == null || inputOffset < 0
+ || inputLen > (input.length - inputOffset) || inputLen < 0) {
+ throw new IllegalArgumentException("Bad arguments");
+ }
+
+ chooseFirstProvider();
+ if (inputLen == 0) {
+ return null;
+ }
+ return spi.engineUpdate(input, inputOffset, inputLen);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
+ * and the result is stored in the <code>output</code> buffer.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * <p>If <code>inputLen</code> is zero, this method returns
+ * a length of zero.
+ *
+ * <p>Note: this method should be copy-safe, which means the
+ * <code>input</code> and <code>output</code> buffers can reference
+ * the same byte array and no unprocessed input data is overwritten
+ * when the result is copied into the output buffer.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ */
+ public final int update(byte[] input, int inputOffset, int inputLen,
+ byte[] output)
+ throws ShortBufferException {
+ checkCipherState();
+
+ // Input sanity check
+ if (input == null || inputOffset < 0
+ || inputLen > (input.length - inputOffset) || inputLen < 0) {
+ throw new IllegalArgumentException("Bad arguments");
+ }
+
+ chooseFirstProvider();
+ if (inputLen == 0) {
+ return 0;
+ }
+ return spi.engineUpdate(input, inputOffset, inputLen,
+ output, 0);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
+ * and the result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code> inclusive.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * <p>If <code>inputLen</code> is zero, this method returns
+ * a length of zero.
+ *
+ * <p>Note: this method should be copy-safe, which means the
+ * <code>input</code> and <code>output</code> buffers can reference
+ * the same byte array and no unprocessed input data is overwritten
+ * when the result is copied into the output buffer.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ */
+ public final int update(byte[] input, int inputOffset, int inputLen,
+ byte[] output, int outputOffset)
+ throws ShortBufferException {
+ checkCipherState();
+
+ // Input sanity check
+ if (input == null || inputOffset < 0
+ || inputLen > (input.length - inputOffset) || inputLen < 0
+ || outputOffset < 0) {
+ throw new IllegalArgumentException("Bad arguments");
+ }
+
+ chooseFirstProvider();
+ if (inputLen == 0) {
+ return 0;
+ }
+ return spi.engineUpdate(input, inputOffset, inputLen,
+ output, outputOffset);
+ }
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>All <code>input.remaining()</code> bytes starting at
+ * <code>input.position()</code> are processed. The result is stored
+ * in the output buffer.
+ * Upon return, the input buffer's position will be equal
+ * to its limit; its limit will not have changed. The output buffer's
+ * position will have advanced by n, where n is the value returned
+ * by this method; the output buffer's limit will not have changed.
+ *
+ * <p>If <code>output.remaining()</code> bytes are insufficient to
+ * hold the result, a <code>ShortBufferException</code> is thrown.
+ * In this case, repeat this call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * <p>Note: this method should be copy-safe, which means the
+ * <code>input</code> and <code>output</code> buffers can reference
+ * the same block of memory and no unprocessed input data is overwritten
+ * when the result is copied into the output buffer.
+ *
+ * @param input the input ByteBuffer
+ * @param output the output ByteByffer
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalArgumentException if input and output are the
+ * same object
+ * @exception ReadOnlyBufferException if the output buffer is read-only
+ * @exception ShortBufferException if there is insufficient space in the
+ * output buffer
+ * @since 1.5
+ */
+ public final int update(ByteBuffer input, ByteBuffer output)
+ throws ShortBufferException {
+ checkCipherState();
+
+ if ((input == null) || (output == null)) {
+ throw new IllegalArgumentException("Buffers must not be null");
+ }
+ if (input == output) {
+ throw new IllegalArgumentException("Input and output buffers must "
+ + "not be the same object, consider using buffer.duplicate()");
+ }
+ if (output.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+
+ chooseFirstProvider();
+ return spi.engineUpdate(input, output);
+ }
+
+ /**
+ * Finishes a multiple-part encryption or decryption operation, depending
+ * on how this cipher was initialized.
+ *
+ * <p>Input data that may have been buffered during a previous
+ * <code>update</code> operation is processed, with padding (if requested)
+ * being applied.
+ * The result is stored in a new buffer.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * @return the new buffer with the result
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final byte[] doFinal()
+ throws IllegalBlockSizeException, BadPaddingException {
+ checkCipherState();
+
+ chooseFirstProvider();
+ return spi.engineDoFinal(null, 0, 0);
+ }
+
+ /**
+ * Finishes a multiple-part encryption or decryption operation, depending
+ * on how this cipher was initialized.
+ *
+ * <p>Input data that may have been buffered during a previous
+ * <code>update</code> operation is processed, with padding (if requested)
+ * being applied.
+ * The result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code> inclusive.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final int doFinal(byte[] output, int outputOffset)
+ throws IllegalBlockSizeException, ShortBufferException,
+ BadPaddingException {
+ checkCipherState();
+
+ // Input sanity check
+ if ((output == null) || (outputOffset < 0)) {
+ throw new IllegalArgumentException("Bad arguments");
+ }
+
+ chooseFirstProvider();
+ return spi.engineDoFinal(null, 0, 0, output, outputOffset);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ *
+ * <p>The bytes in the <code>input</code> buffer, and any input bytes that
+ * may have been buffered during a previous <code>update</code> operation,
+ * are processed, with padding (if requested) being applied.
+ * The result is stored in a new buffer.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * @param input the input buffer
+ *
+ * @return the new buffer with the result
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final byte[] doFinal(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException {
+ checkCipherState();
+
+ // Input sanity check
+ if (input == null) {
+ throw new IllegalArgumentException("Null input buffer");
+ }
+
+ chooseFirstProvider();
+ return spi.engineDoFinal(input, 0, input.length);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
+ * bytes that may have been buffered during a previous <code>update</code>
+ * operation, are processed, with padding (if requested) being applied.
+ * The result is stored in a new buffer.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ *
+ * @return the new buffer with the result
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ checkCipherState();
+
+ // Input sanity check
+ if (input == null || inputOffset < 0
+ || inputLen > (input.length - inputOffset) || inputLen < 0) {
+ throw new IllegalArgumentException("Bad arguments");
+ }
+
+ chooseFirstProvider();
+ return spi.engineDoFinal(input, inputOffset, inputLen);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
+ * bytes that may have been buffered during a previous <code>update</code>
+ * operation, are processed, with padding (if requested) being applied.
+ * The result is stored in the <code>output</code> buffer.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * <p>Note: this method should be copy-safe, which means the
+ * <code>input</code> and <code>output</code> buffers can reference
+ * the same byte array and no unprocessed input data is overwritten
+ * when the result is copied into the output buffer.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final int doFinal(byte[] input, int inputOffset, int inputLen,
+ byte[] output)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ checkCipherState();
+
+ // Input sanity check
+ if (input == null || inputOffset < 0
+ || inputLen > (input.length - inputOffset) || inputLen < 0) {
+ throw new IllegalArgumentException("Bad arguments");
+ }
+
+ chooseFirstProvider();
+ return spi.engineDoFinal(input, inputOffset, inputLen,
+ output, 0);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
+ * bytes that may have been buffered during a previous
+ * <code>update</code> operation, are processed, with padding
+ * (if requested) being applied.
+ * The result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code> inclusive.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * <p>Note: this method should be copy-safe, which means the
+ * <code>input</code> and <code>output</code> buffers can reference
+ * the same byte array and no unprocessed input data is overwritten
+ * when the result is copied into the output buffer.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ public final int doFinal(byte[] input, int inputOffset, int inputLen,
+ byte[] output, int outputOffset)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ checkCipherState();
+
+ // Input sanity check
+ if (input == null || inputOffset < 0
+ || inputLen > (input.length - inputOffset) || inputLen < 0
+ || outputOffset < 0) {
+ throw new IllegalArgumentException("Bad arguments");
+ }
+
+ chooseFirstProvider();
+ return spi.engineDoFinal(input, inputOffset, inputLen,
+ output, outputOffset);
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted,
+ * depending on how this cipher was initialized.
+ *
+ * <p>All <code>input.remaining()</code> bytes starting at
+ * <code>input.position()</code> are processed. The result is stored
+ * in the output buffer.
+ * Upon return, the input buffer's position will be equal
+ * to its limit; its limit will not have changed. The output buffer's
+ * position will have advanced by n, where n is the value returned
+ * by this method; the output buffer's limit will not have changed.
+ *
+ * <p>If <code>output.remaining()</code> bytes are insufficient to
+ * hold the result, a <code>ShortBufferException</code> is thrown.
+ * In this case, repeat this call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to <code>init</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>init</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * <p>Note: this method should be copy-safe, which means the
+ * <code>input</code> and <code>output</code> buffers can reference
+ * the same byte array and no unprocessed input data is overwritten
+ * when the result is copied into the output buffer.
+ *
+ * @param input the input ByteBuffer
+ * @param output the output ByteBuffer
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized)
+ * @exception IllegalArgumentException if input and output are the
+ * same object
+ * @exception ReadOnlyBufferException if the output buffer is read-only
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception ShortBufferException if there is insufficient space in the
+ * output buffer
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ * @since 1.5
+ */
+ public final int doFinal(ByteBuffer input, ByteBuffer output)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ checkCipherState();
+
+ if ((input == null) || (output == null)) {
+ throw new IllegalArgumentException("Buffers must not be null");
+ }
+ if (input == output) {
+ throw new IllegalArgumentException("Input and output buffers must "
+ + "not be the same object, consider using buffer.duplicate()");
+ }
+ if (output.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+
+ chooseFirstProvider();
+ return spi.engineDoFinal(input, output);
+ }
+
+ /**
+ * Wrap a key.
+ *
+ * @param key the key to be wrapped.
+ *
+ * @return the wrapped key.
+ *
+ * @exception IllegalStateException if this cipher is in a wrong
+ * state (e.g., has not been initialized).
+ *
+ * @exception IllegalBlockSizeException if this cipher is a block
+ * cipher, no padding has been requested, and the length of the
+ * encoding of the key to be wrapped is not a
+ * multiple of the block size.
+ *
+ * @exception InvalidKeyException if it is impossible or unsafe to
+ * wrap the key with this cipher (e.g., a hardware protected key is
+ * being passed to a software-only cipher).
+ */
+ public final byte[] wrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException {
+ if (!(this instanceof NullCipher)) {
+ if (!initialized) {
+ throw new IllegalStateException("Cipher not initialized");
+ }
+ if (opmode != Cipher.WRAP_MODE) {
+ throw new IllegalStateException("Cipher not initialized " +
+ "for wrapping keys");
+ }
+ }
+
+ chooseFirstProvider();
+ return spi.engineWrap(key);
+ }
+
+ /**
+ * Unwrap a previously wrapped key.
+ *
+ * @param wrappedKey the key to be unwrapped.
+ *
+ * @param wrappedKeyAlgorithm the algorithm associated with the wrapped
+ * key.
+ *
+ * @param wrappedKeyType the type of the wrapped key. This must be one of
+ * <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or
+ * <code>PUBLIC_KEY</code>.
+ *
+ * @return the unwrapped key.
+ *
+ * @exception IllegalStateException if this cipher is in a wrong state
+ * (e.g., has not been initialized).
+ *
+ * @exception NoSuchAlgorithmException if no installed providers
+ * can create keys of type <code>wrappedKeyType</code> for the
+ * <code>wrappedKeyAlgorithm</code>.
+ *
+ * @exception InvalidKeyException if <code>wrappedKey</code> does not
+ * represent a wrapped key of type <code>wrappedKeyType</code> for
+ * the <code>wrappedKeyAlgorithm</code>.
+ */
+ public final Key unwrap(byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+
+ if (!(this instanceof NullCipher)) {
+ if (!initialized) {
+ throw new IllegalStateException("Cipher not initialized");
+ }
+ if (opmode != Cipher.UNWRAP_MODE) {
+ throw new IllegalStateException("Cipher not initialized " +
+ "for unwrapping keys");
+ }
+ }
+ if ((wrappedKeyType != SECRET_KEY) &&
+ (wrappedKeyType != PRIVATE_KEY) &&
+ (wrappedKeyType != PUBLIC_KEY)) {
+ throw new InvalidParameterException("Invalid key type");
+ }
+
+ chooseFirstProvider();
+ return spi.engineUnwrap(wrappedKey,
+ wrappedKeyAlgorithm,
+ wrappedKeyType);
+ }
+
+ private AlgorithmParameterSpec getAlgorithmParameterSpec(
+ AlgorithmParameters params)
+ throws InvalidParameterSpecException {
+ if (params == null) {
+ return null;
+ }
+
+ String alg = params.getAlgorithm().toUpperCase(Locale.ENGLISH);
+
+ if (alg.equalsIgnoreCase("RC2")) {
+ return params.getParameterSpec(RC2ParameterSpec.class);
+ }
+
+ if (alg.equalsIgnoreCase("RC5")) {
+ return params.getParameterSpec(RC5ParameterSpec.class);
+ }
+
+ if (alg.startsWith("PBE")) {
+ return params.getParameterSpec(PBEParameterSpec.class);
+ }
+
+ if (alg.startsWith("DES")) {
+ return params.getParameterSpec(IvParameterSpec.class);
+ }
+ return null;
+ }
+
+ // Used by getMaxAllowedKeyLength and getMaxAllowedParameterSpec
+ // always returns CryptoAllPermission. Old stuff from bad old days.
+ private static CryptoPermission getConfiguredPermission(
+ String transformation) throws NullPointerException,
+ NoSuchAlgorithmException {
+ if (transformation == null) throw new NullPointerException();
+ // Called to make sure it is a valid transformation.
+ tokenizeTransformation(transformation);
+ return CryptoAllPermission.INSTANCE;
+ }
+
+ /**
+ * Returns the maximum key length for the specified transformation
+ * according to the installed JCE jurisdiction policy files. If
+ * JCE unlimited strength jurisdiction policy files are installed,
+ * Integer.MAX_VALUE will be returned.
+ * For more information on default key size in JCE jurisdiction
+ * policy files, please see Appendix E in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppE">
+ * Java Cryptography Architecture Reference Guide</a>.
+ *
+ * @param transformation the cipher transformation.
+ * @return the maximum key length in bits or Integer.MAX_VALUE.
+ * @exception NullPointerException if <code>transformation</code> is null.
+ * @exception NoSuchAlgorithmException if <code>transformation</code>
+ * is not a valid transformation, i.e. in the form of "algorithm" or
+ * "algorithm/mode/padding".
+ * @since 1.5
+ */
+ public static final int getMaxAllowedKeyLength(String transformation)
+ throws NoSuchAlgorithmException {
+ CryptoPermission cp = getConfiguredPermission(transformation);
+ return cp.getMaxKeySize();
+ }
+
+ /**
+ * Returns an AlgorithmParameterSpec object which contains
+ * the maximum cipher parameter value according to the
+ * jurisdiction policy file. If JCE unlimited strength jurisdiction
+ * policy files are installed or there is no maximum limit on the
+ * parameters for the specified transformation in the policy file,
+ * null will be returned.
+ *
+ * @param transformation the cipher transformation.
+ * @return an AlgorithmParameterSpec which holds the maximum
+ * value or null.
+ * @exception NullPointerException if <code>transformation</code>
+ * is null.
+ * @exception NoSuchAlgorithmException if <code>transformation</code>
+ * is not a valid transformation, i.e. in the form of "algorithm" or
+ * "algorithm/mode/padding".
+ * @since 1.5
+ */
+ public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
+ String transformation) throws NoSuchAlgorithmException {
+ CryptoPermission cp = getConfiguredPermission(transformation);
+ return cp.getAlgorithmParameterSpec();
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/CipherInputStream.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/CipherInputStream.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/CipherInputStream.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,322 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.io.*;
+
+/**
+ * A CipherInputStream is composed of an InputStream and a Cipher so
+ * that read() methods return data that are read in from the
+ * underlying InputStream but have been additionally processed by the
+ * Cipher. The Cipher must be fully initialized before being used by
+ * a CipherInputStream.
+ *
+ * <p> For example, if the Cipher is initialized for decryption, the
+ * CipherInputStream will attempt to read in data and decrypt them,
+ * before returning the decrypted data.
+ *
+ * <p> This class adheres strictly to the semantics, especially the
+ * failure semantics, of its ancestor classes
+ * java.io.FilterInputStream and java.io.InputStream. This class has
+ * exactly those methods specified in its ancestor classes, and
+ * overrides them all. Moreover, this class catches all exceptions
+ * that are not thrown by its ancestor classes. In particular, the
+ * <code>skip</code> method skips, and the <code>available</code>
+ * method counts only data that have been processed by the encapsulated Cipher.
+ *
+ * <p> It is crucial for a programmer using this class not to use
+ * methods that are not defined or overriden in this class (such as a
+ * new method or constructor that is later added to one of the super
+ * classes), because the design and implementation of those methods
+ * are unlikely to have considered security impact with regard to
+ * CipherInputStream.
+ *
+ * @author Li Gong
+ * @see java.io.InputStream
+ * @see java.io.FilterInputStream
+ * @see javax.crypto.Cipher
+ * @see javax.crypto.CipherOutputStream
+ *
+ * @since 1.4
+ */
+
+public class CipherInputStream extends FilterInputStream {
+
+ // the cipher engine to use to process stream data
+ private Cipher cipher;
+
+ // the underlying input stream
+ private InputStream input;
+
+ /* the buffer holding data that have been read in from the
+ underlying stream, but have not been processed by the cipher
+ engine. the size 512 bytes is somewhat randomly chosen */
+ private byte[] ibuffer = new byte[512];
+
+ // having reached the end of the underlying input stream
+ private boolean done = false;
+
+ /* the buffer holding data that have been processed by the cipher
+ engine, but have not been read out */
+ private byte[] obuffer;
+ // the offset pointing to the next "new" byte
+ private int ostart = 0;
+ // the offset pointing to the last "new" byte
+ private int ofinish = 0;
+
+ /**
+ * private convenience function.
+ *
+ * Entry condition: ostart = ofinish
+ *
+ * Exit condition: ostart <= ofinish
+ *
+ * return (ofinish-ostart) (we have this many bytes for you)
+ * return 0 (no data now, but could have more later)
+ * return -1 (absolutely no more data)
+ */
+ private int getMoreData() throws IOException {
+ if (done) return -1;
+ int readin = input.read(ibuffer);
+ if (readin == -1) {
+ done = true;
+ try {
+ obuffer = cipher.doFinal();
+ }
+ catch (IllegalBlockSizeException e) {obuffer = null;}
+ catch (BadPaddingException e) {obuffer = null;}
+ if (obuffer == null)
+ return -1;
+ else {
+ ostart = 0;
+ ofinish = obuffer.length;
+ return ofinish;
+ }
+ }
+ try {
+ obuffer = cipher.update(ibuffer, 0, readin);
+ } catch (IllegalStateException e) {obuffer = null;};
+ ostart = 0;
+ if (obuffer == null)
+ ofinish = 0;
+ else ofinish = obuffer.length;
+ return ofinish;
+ }
+
+ /**
+ * Constructs a CipherInputStream from an InputStream and a
+ * Cipher.
+ * <br>Note: if the specified input stream or cipher is
+ * null, a NullPointerException may be thrown later when
+ * they are used.
+ * @param is the to-be-processed input stream
+ * @param c an initialized Cipher object
+ */
+ public CipherInputStream(InputStream is, Cipher c) {
+ super(is);
+ input = is;
+ cipher = c;
+ }
+
+ /**
+ * Constructs a CipherInputStream from an InputStream without
+ * specifying a Cipher. This has the effect of constructing a
+ * CipherInputStream using a NullCipher.
+ * <br>Note: if the specified input stream is null, a
+ * NullPointerException may be thrown later when it is used.
+ * @param is the to-be-processed input stream
+ */
+ protected CipherInputStream(InputStream is) {
+ super(is);
+ input = is;
+ cipher = new NullCipher();
+ }
+
+ /**
+ * Reads the next byte of data from this input stream. The value
+ * byte is returned as an <code>int</code> in the range
+ * <code>0</code> to <code>255</code>. If no byte is available
+ * because the end of the stream has been reached, the value
+ * <code>-1</code> is returned. This method blocks until input data
+ * is available, the end of the stream is detected, or an exception
+ * is thrown.
+ * <p>
+ *
+ * @return the next byte of data, or <code>-1</code> if the end of the
+ * stream is reached.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public int read() throws IOException {
+ if (ostart >= ofinish) {
+ // we loop for new data as the spec says we are blocking
+ int i = 0;
+ while (i == 0) i = getMoreData();
+ if (i == -1) return -1;
+ }
+ return ((int) obuffer[ostart++] & 0xff);
+ };
+
+ /**
+ * Reads up to <code>b.length</code> bytes of data from this input
+ * stream into an array of bytes.
+ * <p>
+ * The <code>read</code> method of <code>InputStream</code> calls
+ * the <code>read</code> method of three arguments with the arguments
+ * <code>b</code>, <code>0</code>, and <code>b.length</code>.
+ *
+ * @param b the buffer into which the data is read.
+ * @return the total number of bytes read into the buffer, or
+ * <code>-1</code> is there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.InputStream#read(byte[], int, int)
+ * @since JCE1.2
+ */
+ public int read(byte b[]) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ /**
+ * Reads up to <code>len</code> bytes of data from this input stream
+ * into an array of bytes. This method blocks until some input is
+ * available. If the first argument is <code>null,</code> up to
+ * <code>len</code> bytes are read and discarded.
+ *
+ * @param b the buffer into which the data is read.
+ * @param off the start offset in the destination array
+ * <code>buf</code>
+ * @param len the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or
+ * <code>-1</code> if there is no more data because the end of
+ * the stream has been reached.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.InputStream#read()
+ * @since JCE1.2
+ */
+ public int read(byte b[], int off, int len) throws IOException {
+ if (ostart >= ofinish) {
+ // we loop for new data as the spec says we are blocking
+ int i = 0;
+ while (i == 0) i = getMoreData();
+ if (i == -1) return -1;
+ }
+ if (len <= 0) {
+ return 0;
+ }
+ int available = ofinish - ostart;
+ if (len < available) available = len;
+ if (b != null) {
+ System.arraycopy(obuffer, ostart, b, off, available);
+ }
+ ostart = ostart + available;
+ return available;
+ }
+
+ /**
+ * Skips <code>n</code> bytes of input from the bytes that can be read
+ * from this input stream without blocking.
+ *
+ * <p>Fewer bytes than requested might be skipped.
+ * The actual number of bytes skipped is equal to <code>n</code> or
+ * the result of a call to
+ * {@link #available() <code>available</code>},
+ * whichever is smaller.
+ * If <code>n</code> is less than zero, no bytes are skipped.
+ *
+ * <p>The actual number of bytes skipped is returned.
+ *
+ * @param n the number of bytes to be skipped.
+ * @return the actual number of bytes skipped.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public long skip(long n) throws IOException {
+ int available = ofinish - ostart;
+ if (n > available) {
+ n = available;
+ }
+ if (n < 0) {
+ return 0;
+ }
+ ostart += n;
+ return n;
+ }
+
+ /**
+ * Returns the number of bytes that can be read from this input
+ * stream without blocking. The <code>available</code> method of
+ * <code>InputStream</code> returns <code>0</code>. This method
+ * <B>should</B> be overridden by subclasses.
+ *
+ * @return the number of bytes that can be read from this input stream
+ * without blocking.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public int available() throws IOException {
+ return (ofinish - ostart);
+ }
+
+ /**
+ * Closes this input stream and releases any system resources
+ * associated with the stream.
+ * <p>
+ * The <code>close</code> method of <code>CipherInputStream</code>
+ * calls the <code>close</code> method of its underlying input
+ * stream.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void close() throws IOException {
+ input.close();
+ try {
+ // throw away the unprocessed data
+ cipher.doFinal();
+ }
+ catch (BadPaddingException ex) {
+ }
+ catch (IllegalBlockSizeException ex) {
+ }
+ ostart = 0;
+ ofinish = 0;
+ }
+
+ /**
+ * Tests if this input stream supports the <code>mark</code>
+ * and <code>reset</code> methods, which it does not.
+ *
+ * @return <code>false</code>, since this class does not support the
+ * <code>mark</code> and <code>reset</code> methods.
+ * @see java.io.InputStream#mark(int)
+ * @see java.io.InputStream#reset()
+ * @since JCE1.2
+ */
+ public boolean markSupported() {
+ return false;
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/CipherOutputStream.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/CipherOutputStream.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/CipherOutputStream.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,213 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.io.*;
+
+/**
+ * A CipherOutputStream is composed of an OutputStream and a Cipher so
+ * that write() methods first process the data before writing them out
+ * to the underlying OutputStream. The cipher must be fully
+ * initialized before being used by a CipherOutputStream.
+ *
+ * <p> For example, if the cipher is initialized for encryption, the
+ * CipherOutputStream will attempt to encrypt data before writing out the
+ * encrypted data.
+ *
+ * <p> This class adheres strictly to the semantics, especially the
+ * failure semantics, of its ancestor classes
+ * java.io.OutputStream and java.io.FilterOutputStream. This class
+ * has exactly those methods specified in its ancestor classes, and
+ * overrides them all. Moreover, this class catches all exceptions
+ * that are not thrown by its ancestor classes.
+ *
+ * <p> It is crucial for a programmer using this class not to use
+ * methods that are not defined or overriden in this class (such as a
+ * new method or constructor that is later added to one of the super
+ * classes), because the design and implementation of those methods
+ * are unlikely to have considered security impact with regard to
+ * CipherOutputStream.
+ *
+ * @author Li Gong
+ * @see java.io.OutputStream
+ * @see java.io.FilterOutputStream
+ * @see javax.crypto.Cipher
+ * @see javax.crypto.CipherInputStream
+ *
+ * @since 1.4
+ */
+
+public class CipherOutputStream extends FilterOutputStream {
+
+ // the cipher engine to use to process stream data
+ private Cipher cipher;
+
+ // the underlying output stream
+ private OutputStream output;
+
+ /* the buffer holding one byte of incoming data */
+ private byte[] ibuffer = new byte[1];
+
+ // the buffer holding data ready to be written out
+ private byte[] obuffer;
+
+ /**
+ *
+ * Constructs a CipherOutputStream from an OutputStream and a
+ * Cipher.
+ * <br>Note: if the specified output stream or cipher is
+ * null, a NullPointerException may be thrown later when
+ * they are used.
+ *
+ * @param os the OutputStream object
+ * @param c an initialized Cipher object
+ */
+ public CipherOutputStream(OutputStream os, Cipher c) {
+ super(os);
+ output = os;
+ cipher = c;
+ };
+
+ /**
+ * Constructs a CipherOutputStream from an OutputStream without
+ * specifying a Cipher. This has the effect of constructing a
+ * CipherOutputStream using a NullCipher.
+ * <br>Note: if the specified output stream is null, a
+ * NullPointerException may be thrown later when it is used.
+ *
+ * @param os the OutputStream object
+ */
+ protected CipherOutputStream(OutputStream os) {
+ super(os);
+ output = os;
+ cipher = new NullCipher();
+ }
+
+ /**
+ * Writes the specified byte to this output stream.
+ *
+ * @param b the <code>byte</code>.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void write(int b) throws IOException {
+ ibuffer[0] = (byte) b;
+ obuffer = cipher.update(ibuffer, 0, 1);
+ if (obuffer != null) {
+ output.write(obuffer);
+ obuffer = null;
+ }
+ };
+
+ /**
+ * Writes <code>b.length</code> bytes from the specified byte array
+ * to this output stream.
+ * <p>
+ * The <code>write</code> method of
+ * <code>CipherOutputStream</code> calls the <code>write</code>
+ * method of three arguments with the three arguments
+ * <code>b</code>, <code>0</code>, and <code>b.length</code>.
+ *
+ * @param b the data.
+ * @exception NullPointerException if <code>b</code> is null.
+ * @exception IOException if an I/O error occurs.
+ * @see javax.crypto.CipherOutputStream#write(byte[], int, int)
+ * @since JCE1.2
+ */
+ public void write(byte b[]) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ /**
+ * Writes <code>len</code> bytes from the specified byte array
+ * starting at offset <code>off</code> to this output stream.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void write(byte b[], int off, int len) throws IOException {
+ obuffer = cipher.update(b, off, len);
+ if (obuffer != null) {
+ output.write(obuffer);
+ obuffer = null;
+ }
+ }
+
+ /**
+ * Flushes this output stream by forcing any buffered output bytes
+ * that have already been processed by the encapsulated cipher object
+ * to be written out.
+ *
+ * <p>Any bytes buffered by the encapsulated cipher
+ * and waiting to be processed by it will not be written out. For example,
+ * if the encapsulated cipher is a block cipher, and the total number of
+ * bytes written using one of the <code>write</code> methods is less than
+ * the cipher's block size, no bytes will be written out.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void flush() throws IOException {
+ if (obuffer != null) {
+ output.write(obuffer);
+ obuffer = null;
+ }
+ output.flush();
+ }
+
+ /**
+ * Closes this output stream and releases any system resources
+ * associated with this stream.
+ * <p>
+ * This method invokes the <code>doFinal</code> method of the encapsulated
+ * cipher object, which causes any bytes buffered by the encapsulated
+ * cipher to be processed. The result is written out by calling the
+ * <code>flush</code> method of this output stream.
+ * <p>
+ * This method resets the encapsulated cipher object to its initial state
+ * and calls the <code>close</code> method of the underlying output
+ * stream.
+ *
+ * @exception IOException if an I/O error occurs.
+ * @since JCE1.2
+ */
+ public void close() throws IOException {
+ try {
+ obuffer = cipher.doFinal();
+ } catch (IllegalBlockSizeException e) {
+ obuffer = null;
+ } catch (BadPaddingException e) {
+ obuffer = null;
+ }
+ try {
+ flush();
+ } catch (IOException ignored) {}
+ out.close();
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/CipherSpi.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/CipherSpi.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/CipherSpi.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,895 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.util.StringTokenizer;
+import java.util.NoSuchElementException;
+import java.security.AlgorithmParameters;
+import java.security.Provider;
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.ProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+
+import java.nio.ByteBuffer;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>Cipher</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular cipher algorithm.
+ *
+ * <p>In order to create an instance of <code>Cipher</code>, which
+ * encapsulates an instance of this <code>CipherSpi</code> class, an
+ * application calls one of the
+ * {@link Cipher#getInstance(java.lang.String) getInstance}
+ * factory methods of the
+ * {@link Cipher Cipher} engine class and specifies the requested
+ * <i>transformation</i>.
+ * Optionally, the application may also specify the name of a provider.
+ *
+ * <p>A <i>transformation</i> is a string that describes the operation (or
+ * set of operations) to be performed on the given input, to produce some
+ * output. A transformation always includes the name of a cryptographic
+ * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
+ * padding scheme.
+ *
+ * <p> A transformation is of the form:<p>
+ *
+ * <ul>
+ * <li>"<i>algorithm/mode/padding</i>" or
+ * <p>
+ * <li>"<i>algorithm</i>"
+ * </ul>
+ *
+ * <P> (in the latter case,
+ * provider-specific default values for the mode and padding scheme are used).
+ * For example, the following is a valid transformation:<p>
+ *
+ * <pre>
+ * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
+ * </pre>
+ *
+ * <p>A provider may supply a separate class for each combination
+ * of <i>algorithm/mode/padding</i>, or may decide to provide more generic
+ * classes representing sub-transformations corresponding to
+ * <i>algorithm</i> or <i>algorithm/mode</i> or <i>algorithm//padding</i>
+ * (note the double slashes),
+ * in which case the requested mode and/or padding are set automatically by
+ * the <code>getInstance</code> methods of <code>Cipher</code>, which invoke
+ * the {@link #engineSetMode(java.lang.String) engineSetMode} and
+ * {@link #engineSetPadding(java.lang.String) engineSetPadding}
+ * methods of the provider's subclass of <code>CipherSpi</code>.
+ *
+ * <p>A <code>Cipher</code> property in a provider master class may have one of
+ * the following formats:
+ *
+ * <ul>
+ *
+ * <li>
+ * <pre>
+ * // provider's subclass of "CipherSpi" implements "algName" with
+ * // pluggable mode and padding
+ * <code>Cipher.</code><i>algName</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * // provider's subclass of "CipherSpi" implements "algName" in the
+ * // specified "mode", with pluggable padding
+ * <code>Cipher.</code><i>algName/mode</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * // provider's subclass of "CipherSpi" implements "algName" with the
+ * // specified "padding", with pluggable mode
+ * <code>Cipher.</code><i>algName//padding</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * // provider's subclass of "CipherSpi" implements "algName" with the
+ * // specified "mode" and "padding"
+ * <code>Cipher.</code><i>algName/mode/padding</i>
+ * </pre>
+ *
+ * </ul>
+ *
+ * <p>For example, a provider may supply a subclass of <code>CipherSpi</code>
+ * that implements <i>DES/ECB/PKCS5Padding</i>, one that implements
+ * <i>DES/CBC/PKCS5Padding</i>, one that implements
+ * <i>DES/CFB/PKCS5Padding</i>, and yet another one that implements
+ * <i>DES/OFB/PKCS5Padding</i>. That provider would have the following
+ * <code>Cipher</code> properties in its master class:<p>
+ *
+ * <ul>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES/ECB/PKCS5Padding</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES/CBC/PKCS5Padding</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES/CFB/PKCS5Padding</i>
+ * </pre>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES/OFB/PKCS5Padding</i>
+ * </pre>
+ *
+ * </ul>
+ *
+ * <p>Another provider may implement a class for each of the above modes
+ * (i.e., one class for <i>ECB</i>, one for <i>CBC</i>, one for <i>CFB</i>,
+ * and one for <i>OFB</i>), one class for <i>PKCS5Padding</i>,
+ * and a generic <i>DES</i> class that subclasses from <code>CipherSpi</code>.
+ * That provider would have the following
+ * <code>Cipher</code> properties in its master class:<p>
+ *
+ * <ul>
+ *
+ * <li>
+ * <pre>
+ * <code>Cipher.</code><i>DES</i>
+ * </pre>
+ *
+ * </ul>
+ *
+ * <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
+ * engine class follows these rules in order to instantiate a provider's
+ * implementation of <code>CipherSpi</code> for a
+ * transformation of the form "<i>algorithm</i>":
+ *
+ * <ol>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the specified "<i>algorithm</i>".
+ * <p>If the answer is YES, instantiate this
+ * class, for whose mode and padding scheme default values (as supplied by
+ * the provider) are used.
+ * <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
+ * exception.
+ * </ol>
+ *
+ * <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
+ * engine class follows these rules in order to instantiate a provider's
+ * implementation of <code>CipherSpi</code> for a
+ * transformation of the form "<i>algorithm/mode/padding</i>":
+ *
+ * <ol>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the specified "<i>algorithm/mode/padding</i>" transformation.
+ * <p>If the answer is YES, instantiate it.
+ * <p>If the answer is NO, go to the next step.<p>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the sub-transformation "<i>algorithm/mode</i>".
+ * <p>If the answer is YES, instantiate it, and call
+ * <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
+ * <p>If the answer is NO, go to the next step.<p>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the sub-transformation "<i>algorithm//padding</i>" (note the double
+ * slashes).
+ * <p>If the answer is YES, instantiate it, and call
+ * <code>engineSetMode(<i>mode</i>)</code> on the new instance.
+ * <p>If the answer is NO, go to the next step.<p>
+ * <li>
+ * Check if the provider has registered a subclass of <code>CipherSpi</code>
+ * for the sub-transformation "<i>algorithm</i>".
+ * <p>If the answer is YES, instantiate it, and call
+ * <code>engineSetMode(<i>mode</i>)</code> and
+ * <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
+ * <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
+ * exception.
+ * </ol>
+ *
+ * @author Jan Luehe
+ * @see KeyGenerator
+ * @see SecretKey
+ * @since 1.4
+ */
+
+public abstract class CipherSpi {
+
+ /**
+ * Sets the mode of this cipher.
+ *
+ * @param mode the cipher mode
+ *
+ * @exception NoSuchAlgorithmException if the requested cipher mode does
+ * not exist
+ */
+ protected abstract void engineSetMode(String mode)
+ throws NoSuchAlgorithmException;
+
+ /**
+ * Sets the padding mechanism of this cipher.
+ *
+ * @param padding the padding mechanism
+ *
+ * @exception NoSuchPaddingException if the requested padding mechanism
+ * does not exist
+ */
+ protected abstract void engineSetPadding(String padding)
+ throws NoSuchPaddingException;
+
+ /**
+ * Returns the block size (in bytes).
+ *
+ * @return the block size (in bytes), or 0 if the underlying algorithm is
+ * not a block cipher
+ */
+ protected abstract int engineGetBlockSize();
+
+ /**
+ * Returns the length in bytes that an output buffer would
+ * need to be in order to hold the result of the next <code>update</code>
+ * or <code>doFinal</code> operation, given the input length
+ * <code>inputLen</code> (in bytes).
+ *
+ * <p>This call takes into account any unprocessed (buffered) data from a
+ * previous <code>update</code> call, and padding.
+ *
+ * <p>The actual output length of the next <code>update</code> or
+ * <code>doFinal</code> call may be smaller than the length returned by
+ * this method.
+ *
+ * @param inputLen the input length (in bytes)
+ *
+ * @return the required output buffer size (in bytes)
+ */
+ protected abstract int engineGetOutputSize(int inputLen);
+
+ /**
+ * Returns the initialization vector (IV) in a new buffer.
+ *
+ * <p> This is useful in the context of password-based encryption or
+ * decryption, where the IV is derived from a user-provided passphrase.
+ *
+ * @return the initialization vector in a new buffer, or null if the
+ * underlying algorithm does not use an IV, or if the IV has not yet
+ * been set.
+ */
+ protected abstract byte[] engineGetIV();
+
+ /**
+ * Returns the parameters used with this cipher.
+ *
+ * <p>The returned parameters may be the same that were used to initialize
+ * this cipher, or may contain a combination of default and random
+ * parameter values used by the underlying cipher implementation if this
+ * cipher requires algorithm parameters but was not initialized with any.
+ *
+ * @return the parameters used with this cipher, or null if this cipher
+ * does not use any parameters.
+ */
+ protected abstract AlgorithmParameters engineGetParameters();
+
+ /**
+ * Initializes this cipher with a key and a source
+ * of randomness.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending on
+ * the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters that cannot be
+ * derived from the given <code>key</code>, the underlying cipher
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidKeyException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #engineGetParameters() engineGetParameters} or
+ * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of
+ * the following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher, or if this cipher is being initialized for
+ * decryption and requires algorithm parameters that cannot be
+ * determined from the given key.
+ */
+ protected abstract void engineInit(int opmode, Key key,
+ SecureRandom random)
+ throws InvalidKeyException;
+
+ /**
+ * Initializes this cipher with a key, a set of
+ * algorithm parameters, and a source of randomness.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending on
+ * the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #engineGetParameters() engineGetParameters} or
+ * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of
+ * the following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or if this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null.
+ */
+ protected abstract void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Initializes this cipher with a key, a set of
+ * algorithm parameters, and a source of randomness.
+ *
+ * <p>The cipher is initialized for one of the following four operations:
+ * encryption, decryption, key wrapping or key unwrapping, depending on
+ * the value of <code>opmode</code>.
+ *
+ * <p>If this cipher requires any algorithm parameters and
+ * <code>params</code> is null, the underlying cipher implementation is
+ * supposed to generate the required parameters itself (using
+ * provider-specific default or random values) if it is being
+ * initialized for encryption or key wrapping, and raise an
+ * <code>InvalidAlgorithmParameterException</code> if it is being
+ * initialized for decryption or key unwrapping.
+ * The generated parameters can be retrieved using
+ * {@link #engineGetParameters() engineGetParameters} or
+ * {@link #engineGetIV() engineGetIV} (if the parameter is an IV).
+ *
+ * <p>If this cipher (including its underlying feedback or padding scheme)
+ * requires any random bytes (e.g., for parameter generation), it will get
+ * them from <code>random</code>.
+ *
+ * <p>Note that when a Cipher object is initialized, it loses all
+ * previously-acquired state. In other words, initializing a Cipher is
+ * equivalent to creating a new instance of that Cipher and initializing
+ * it.
+ *
+ * @param opmode the operation mode of this cipher (this is one of
+ * the following:
+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
+ * @param key the encryption key
+ * @param params the algorithm parameters
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this cipher
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this cipher,
+ * or if this cipher is being initialized for decryption and requires
+ * algorithm parameters and <code>params</code> is null.
+ */
+ protected abstract void engineInit(int opmode, Key key,
+ AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
+ * and the result is stored in a new buffer.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ *
+ * @return the new buffer with the result, or null if the underlying
+ * cipher is a block cipher and the input data is too short to result in a
+ * new block.
+ */
+ protected abstract byte[] engineUpdate(byte[] input, int inputOffset,
+ int inputLen);
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
+ * and the result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code> inclusive.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ */
+ protected abstract int engineUpdate(byte[] input, int inputOffset,
+ int inputLen, byte[] output,
+ int outputOffset)
+ throws ShortBufferException;
+
+ /**
+ * Continues a multiple-part encryption or decryption operation
+ * (depending on how this cipher was initialized), processing another data
+ * part.
+ *
+ * <p>All <code>input.remaining()</code> bytes starting at
+ * <code>input.position()</code> are processed. The result is stored
+ * in the output buffer.
+ * Upon return, the input buffer's position will be equal
+ * to its limit; its limit will not have changed. The output buffer's
+ * position will have advanced by n, where n is the value returned
+ * by this method; the output buffer's limit will not have changed.
+ *
+ * <p>If <code>output.remaining()</code> bytes are insufficient to
+ * hold the result, a <code>ShortBufferException</code> is thrown.
+ *
+ * <p>Subclasses should consider overriding this method if they can
+ * process ByteBuffers more efficiently than byte arrays.
+ *
+ * @param input the input ByteBuffer
+ * @param output the output ByteByffer
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception ShortBufferException if there is insufficient space in the
+ * output buffer
+ *
+ * @throws NullPointerException if either parameter is <CODE>null</CODE>
+ * @since 1.5
+ */
+ protected int engineUpdate(ByteBuffer input, ByteBuffer output)
+ throws ShortBufferException {
+ try {
+ return bufferCrypt(input, output, true);
+ } catch (IllegalBlockSizeException e) {
+ // never thrown for engineUpdate()
+ throw new ProviderException("Internal error in update()");
+ } catch (BadPaddingException e) {
+ // never thrown for engineUpdate()
+ throw new ProviderException("Internal error in update()");
+ }
+ }
+
+ /**
+ * Encrypts or decrypts data in a single-part operation,
+ * or finishes a multiple-part operation.
+ * The data is encrypted or decrypted, depending on how this cipher was
+ * initialized.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
+ * bytes that may have been buffered during a previous <code>update</code>
+ * operation, are processed, with padding (if requested) being applied.
+ * The result is stored in a new buffer.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to
+ * <code>engineInit</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>engineInit</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ *
+ * @return the new buffer with the result
+ *
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ protected abstract byte[] engineDoFinal(byte[] input, int inputOffset,
+ int inputLen)
+ throws IllegalBlockSizeException, BadPaddingException;
+
+ /**
+ * Encrypts or decrypts data in a single-part operation,
+ * or finishes a multiple-part operation.
+ * The data is encrypted or decrypted, depending on how this cipher was
+ * initialized.
+ *
+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
+ * bytes that may have been buffered during a previous <code>update</code>
+ * operation, are processed, with padding (if requested) being applied.
+ * The result is stored in the <code>output</code> buffer, starting at
+ * <code>outputOffset</code> inclusive.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to
+ * <code>engineInit</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>engineInit</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * @param input the input buffer
+ * @param inputOffset the offset in <code>input</code> where the input
+ * starts
+ * @param inputLen the input length
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ */
+ protected abstract int engineDoFinal(byte[] input, int inputOffset,
+ int inputLen, byte[] output,
+ int outputOffset)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException;
+
+ /**
+ * Encrypts or decrypts data in a single-part operation,
+ * or finishes a multiple-part operation.
+ * The data is encrypted or decrypted, depending on how this cipher was
+ * initialized.
+ *
+ * <p>All <code>input.remaining()</code> bytes starting at
+ * <code>input.position()</code> are processed. The result is stored
+ * in the output buffer.
+ * Upon return, the input buffer's position will be equal
+ * to its limit; its limit will not have changed. The output buffer's
+ * position will have advanced by n, where n is the value returned
+ * by this method; the output buffer's limit will not have changed.
+ *
+ * <p>If <code>output.remaining()</code> bytes are insufficient to
+ * hold the result, a <code>ShortBufferException</code> is thrown.
+ *
+ * <p>Upon finishing, this method resets this cipher object to the state
+ * it was in when previously initialized via a call to
+ * <code>engineInit</code>.
+ * That is, the object is reset and available to encrypt or decrypt
+ * (depending on the operation mode that was specified in the call to
+ * <code>engineInit</code>) more data.
+ *
+ * <p>Note: if any exception is thrown, this cipher object may need to
+ * be reset before it can be used again.
+ *
+ * <p>Subclasses should consider overriding this method if they can
+ * process ByteBuffers more efficiently than byte arrays.
+ *
+ * @param input the input ByteBuffer
+ * @param output the output ByteByffer
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested (only in encryption mode), and the total
+ * input length of the data processed by this cipher is not a multiple of
+ * block size; or if this encryption algorithm is unable to
+ * process the input data provided.
+ * @exception ShortBufferException if there is insufficient space in the
+ * output buffer
+ * @exception BadPaddingException if this cipher is in decryption mode,
+ * and (un)padding has been requested, but the decrypted data is not
+ * bounded by the appropriate padding bytes
+ *
+ * @throws NullPointerException if either parameter is <CODE>null</CODE>
+ * @since 1.5
+ */
+ protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ return bufferCrypt(input, output, false);
+ }
+
+ // copied from sun.security.jca.JCAUtil
+ // will be changed to reference that method once that code has been
+ // integrated and promoted
+ static int getTempArraySize(int totalSize) {
+ return Math.min(4096, totalSize);
+ }
+
+ /**
+ * Implementation for encryption using ByteBuffers. Used for both
+ * engineUpdate() and engineDoFinal().
+ */
+ private int bufferCrypt(ByteBuffer input, ByteBuffer output,
+ boolean isUpdate) throws ShortBufferException,
+ IllegalBlockSizeException, BadPaddingException {
+ if ((input == null) || (output == null)) {
+ throw new NullPointerException
+ ("Input and output buffers must not be null");
+ }
+ int inPos = input.position();
+ int inLimit = input.limit();
+ int inLen = inLimit - inPos;
+ if (isUpdate && (inLen == 0)) {
+ return 0;
+ }
+ int outLenNeeded = engineGetOutputSize(inLen);
+ if (output.remaining() < outLenNeeded) {
+ throw new ShortBufferException("Need at least " + outLenNeeded
+ + " bytes of space in output buffer");
+ }
+
+ boolean a1 = input.hasArray();
+ boolean a2 = output.hasArray();
+
+ if (a1 && a2) {
+ byte[] inArray = input.array();
+ int inOfs = input.arrayOffset() + inPos;
+ byte[] outArray = output.array();
+ int outPos = output.position();
+ int outOfs = output.arrayOffset() + outPos;
+ int n;
+ if (isUpdate) {
+ n = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
+ } else {
+ n = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
+ }
+ input.position(inLimit);
+ output.position(outPos + n);
+ return n;
+ } else if (!a1 && a2) {
+ int outPos = output.position();
+ byte[] outArray = output.array();
+ int outOfs = output.arrayOffset() + outPos;
+ byte[] inArray = new byte[getTempArraySize(inLen)];
+ int total = 0;
+ while (inLen > 0) {
+ int chunk = Math.min(inLen, inArray.length);
+ input.get(inArray, 0, chunk);
+ int n;
+ if (isUpdate || (inLen != chunk)) {
+ n = engineUpdate(inArray, 0, chunk, outArray, outOfs);
+ } else {
+ n = engineDoFinal(inArray, 0, chunk, outArray, outOfs);
+ }
+ total += n;
+ outOfs += n;
+ inLen -= chunk;
+ }
+ output.position(outPos + total);
+ return total;
+ } else { // output is not backed by an accessible byte[]
+ byte[] inArray;
+ int inOfs;
+ if (a1) {
+ inArray = input.array();
+ inOfs = input.arrayOffset() + inPos;
+ } else {
+ inArray = new byte[getTempArraySize(inLen)];
+ inOfs = 0;
+ }
+ byte[] outArray = new byte[getTempArraySize(outLenNeeded)];
+ int outSize = outArray.length;
+ int total = 0;
+ boolean resized = false;
+ while (inLen > 0) {
+ int chunk = Math.min(inLen, outSize);
+ if ((a1 == false) && (resized == false)) {
+ input.get(inArray, 0, chunk);
+ inOfs = 0;
+ }
+ try {
+ int n;
+ if (isUpdate || (inLen != chunk)) {
+ n = engineUpdate(inArray, inOfs, chunk, outArray, 0);
+ } else {
+ n = engineDoFinal(inArray, inOfs, chunk, outArray, 0);
+ }
+ resized = false;
+ inOfs += chunk;
+ inLen -= chunk;
+ output.put(outArray, 0, n);
+ total += n;
+ } catch (ShortBufferException e) {
+ if (resized) {
+ // we just resized the output buffer, but it still
+ // did not work. Bug in the provider, abort
+ throw (ProviderException)new ProviderException
+ ("Could not determine buffer size").initCause(e);
+ }
+ // output buffer is too small, realloc and try again
+ resized = true;
+ int newOut = engineGetOutputSize(chunk);
+ outArray = new byte[newOut];
+ }
+ }
+ input.position(inLimit);
+ return total;
+ }
+ }
+
+ /**
+ * Wrap a key.
+ *
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class. (For backwards compatibility, it cannot be abstract.)
+ * It may be overridden by a provider to wrap a key.
+ * Such an override is expected to throw an IllegalBlockSizeException or
+ * InvalidKeyException (under the specified circumstances),
+ * if the given key cannot be wrapped.
+ * If this method is not overridden, it always throws an
+ * UnsupportedOperationException.
+ *
+ * @param key the key to be wrapped.
+ *
+ * @return the wrapped key.
+ *
+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
+ * no padding has been requested, and the length of the encoding of the
+ * key to be wrapped is not a multiple of the block size.
+ *
+ * @exception InvalidKeyException if it is impossible or unsafe to
+ * wrap the key with this cipher (e.g., a hardware protected key is
+ * being passed to a software-only cipher).
+ */
+ protected byte[] engineWrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unwrap a previously wrapped key.
+ *
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class. (For backwards compatibility, it cannot be abstract.)
+ * It may be overridden by a provider to unwrap a previously wrapped key.
+ * Such an override is expected to throw an InvalidKeyException if
+ * the given wrapped key cannot be unwrapped.
+ * If this method is not overridden, it always throws an
+ * UnsupportedOperationException.
+ *
+ * @param wrappedKey the key to be unwrapped.
+ *
+ * @param wrappedKeyAlgorithm the algorithm associated with the wrapped
+ * key.
+ *
+ * @param wrappedKeyType the type of the wrapped key. This is one of
+ * <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or
+ * <code>PUBLIC_KEY</code>.
+ *
+ * @return the unwrapped key.
+ *
+ * @exception NoSuchAlgorithmException if no installed providers
+ * can create keys of type <code>wrappedKeyType</code> for the
+ * <code>wrappedKeyAlgorithm</code>.
+ *
+ * @exception InvalidKeyException if <code>wrappedKey</code> does not
+ * represent a wrapped key of type <code>wrappedKeyType</code> for
+ * the <code>wrappedKeyAlgorithm</code>.
+ */
+ protected Key engineUnwrap(byte[] wrappedKey,
+ String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the key size of the given key object in bits.
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class. It throws an <code>UnsupportedOperationException</code>
+ * if it is not overridden by the provider.
+ *
+ * @param key the key object.
+ *
+ * @return the key size of the given key object.
+ *
+ * @exception InvalidKeyException if <code>key</code> is invalid.
+ */
+ protected int engineGetKeySize(Key key)
+ throws InvalidKeyException
+ {
+ throw new UnsupportedOperationException();
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoAllPermission.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoAllPermission.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoAllPermission.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,179 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.*;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * The CryptoAllPermission is a permission that implies
+ * any other crypto permissions.
+ * <p>
+ *
+ * @see java.security.Permission
+ * @see java.security.AllPermission
+ *
+ * @author Sharon Liu
+ * @since 1.4
+ */
+
+final class CryptoAllPermission extends CryptoPermission {
+
+ private static final long serialVersionUID = -5066513634293192112L;
+
+ // This class is similar to java.security.AllPermission.
+ static final String ALG_NAME = "CryptoAllPermission";
+ static final CryptoAllPermission INSTANCE =
+ new CryptoAllPermission();
+
+ private CryptoAllPermission() {
+ super(ALG_NAME);
+ }
+
+ /**
+ * Checks if the specified permission is implied by
+ * this object.
+ *
+ * @param p the permission to check against.
+ *
+ * @return true if the specified permission is an
+ * instance of CryptoPermission.
+ */
+ public boolean implies(Permission p) {
+ return (p instanceof CryptoPermission);
+ }
+
+ /**
+ * Checks two CryptoAllPermission objects for equality.
+ * Two CryptoAllPermission objects are always equal.
+ *
+ * @param obj the object to test for equality with this object.
+ *
+ * @return true if <i>obj</i> is a CryptoAllPermission object.
+ */
+ public boolean equals(Object obj) {
+ return (obj == INSTANCE);
+ }
+
+ /**
+ *
+ * Returns the hash code value for this object.
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return 1;
+ }
+
+ /**
+ * Returns a new PermissionCollection object for storing
+ * CryptoAllPermission objects.
+ * <p>
+ *
+ * @return a new PermissionCollection object suitable for
+ * storing CryptoAllPermissions.
+ */
+ public PermissionCollection newPermissionCollection() {
+ return new CryptoAllPermissionCollection();
+ }
+}
+
+/**
+ * A CryptoAllPermissionCollection stores a collection
+ * of CryptoAllPermission permissions.
+ *
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see javax.crypto.CryptoPermission
+ *
+ * @author Sharon Liu
+ */
+final class CryptoAllPermissionCollection extends PermissionCollection
+ implements java.io.Serializable
+{
+
+ private static final long serialVersionUID = 7450076868380144072L;
+
+ // true if a CryptoAllPermission has been added
+ private boolean all_allowed;
+
+ /**
+ * Create an empty CryptoAllPermissions object.
+ */
+ CryptoAllPermissionCollection() {
+ all_allowed = false;
+ }
+
+ /**
+ * Adds a permission to the CryptoAllPermissions.
+ *
+ * @param permission the Permission object to add.
+ *
+ * @exception SecurityException - if this CryptoAllPermissionCollection
+ * object has been marked readonly
+ */
+ public void add(Permission permission)
+ {
+ if (isReadOnly())
+ throw new SecurityException("attempt to add a Permission to " +
+ "a readonly PermissionCollection");
+
+ if (permission != CryptoAllPermission.INSTANCE)
+ return;
+
+ all_allowed = true;
+ }
+
+ /**
+ * Check and see if this set of permissions implies the permissions
+ * expressed in "permission".
+ *
+ * @param p the Permission object to compare
+ *
+ * @return true if the given permission is implied by this
+ * CryptoAllPermissionCollection.
+ */
+ public boolean implies(Permission permission)
+ {
+ if (!(permission instanceof CryptoPermission)) {
+ return false;
+ }
+ return all_allowed;
+ }
+
+ /**
+ * Returns an enumeration of all the CryptoAllPermission
+ * objects in the container.
+ *
+ * @return an enumeration of all the CryptoAllPermission objects.
+ */
+ public Enumeration elements() {
+ Vector v = new Vector(1);
+ if (all_allowed) v.add(CryptoAllPermission.INSTANCE);
+ return v.elements();
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPermission.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPermission.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPermission.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,545 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.crypto.spec.*;
+
+/**
+ * The CryptoPermission class extends the
+ * java.security.Permission class. A
+ * CryptoPermission object is used to represent
+ * the ability of an application/applet to use certain
+ * algorithms with certain key sizes and other
+ * restrictions in certain environments. <p>
+ *
+ * @see java.security.Permission
+ *
+ * @author Jan Luehe
+ * @author Sharon Liu
+ * @since 1.4
+ */
+class CryptoPermission extends java.security.Permission {
+
+ private static final long serialVersionUID = 8987399626114087514L;
+
+ private String alg;
+ private int maxKeySize = Integer.MAX_VALUE; // no restriction on maxKeySize
+ private String exemptionMechanism = null;
+ private AlgorithmParameterSpec algParamSpec = null;
+ private boolean checkParam = false; // no restriction on param
+
+ static final String ALG_NAME_WILDCARD = "*";
+
+ /**
+ * Constructor that takes an algorithm name.
+ *
+ * This constructor implies that the given algorithm can be
+ * used without any restrictions.
+ *
+ * @param alg the algorithm name.
+ */
+ CryptoPermission(String alg) {
+ super(null);
+ this.alg = alg;
+ }
+
+ /**
+ * Constructor that takes an algorithm name and a maximum
+ * key size.
+ *
+ * This constructor implies that the given algorithm can be
+ * used with a key size up to <code>maxKeySize</code>.
+ *
+ * @param alg the algorithm name.
+ *
+ * @param maxKeySize the maximum allowable key size,
+ * specified in number of bits.
+ */
+ CryptoPermission(String alg, int maxKeySize) {
+ super(null);
+ this.alg = alg;
+ this.maxKeySize = maxKeySize;
+ }
+
+ /**
+ * Constructor that takes an algorithm name, a maximum
+ * key size, and an AlgorithmParameterSpec object.
+ *
+ * This constructor implies that the given algorithm can be
+ * used with a key size up to <code>maxKeySize</code>, and
+ * algorithm
+ * parameters up to the limits set in <code>algParamSpec</code>.
+ *
+ * @param alg the algorithm name.
+ *
+ * @param maxKeySize the maximum allowable key size,
+ * specified in number of bits.
+ *
+ * @param algParamSpec the limits for allowable algorithm
+ * parameters.
+ */
+ CryptoPermission(String alg,
+ int maxKeySize,
+ AlgorithmParameterSpec algParamSpec) {
+ super(null);
+ this.alg = alg;
+ this.maxKeySize = maxKeySize;
+ this.checkParam = true;
+ this.algParamSpec = algParamSpec;
+ }
+
+ /**
+ * Constructor that takes an algorithm name and the name of
+ * an exemption mechanism.
+ *
+ * This constructor implies that the given algorithm can be
+ * used without any key size or algorithm parameter restrictions
+ * provided that the specified exemption mechanism is enforced.
+ *
+ * @param alg the algorithm name.
+ *
+ * @param exemptionMechanism the name of the exemption mechanism.
+ */
+ CryptoPermission(String alg,
+ String exemptionMechanism) {
+ super(null);
+ this.alg = alg;
+ this.exemptionMechanism = exemptionMechanism;
+ }
+
+ /**
+ * Constructor that takes an algorithm name, a maximum key
+ * size, and the name of an exemption mechanism.
+ *
+ * This constructor implies that the given algorithm can be
+ * used with a key size up to <code>maxKeySize</code>
+ * provided that the
+ * specified exemption mechanism is enforced.
+ *
+ * @param alg the algorithm name.
+ * @param maxKeySize the maximum allowable key size,
+ * specified in number of bits.
+ * @param exemptionMechanism the name of the exemption
+ * mechanism.
+ */
+ CryptoPermission(String alg,
+ int maxKeySize,
+ String exemptionMechanism) {
+ super(null);
+ this.alg = alg;
+ this.exemptionMechanism = exemptionMechanism;
+ this.maxKeySize = maxKeySize;
+ }
+
+ /**
+ * Constructor that takes an algorithm name, a maximum key
+ * size, the name of an exemption mechanism, and an
+ * AlgorithmParameterSpec object.
+ *
+ * This constructor implies that the given algorithm can be
+ * used with a key size up to <code>maxKeySize</code>
+ * and algorithm
+ * parameters up to the limits set in <code>algParamSpec</code>
+ * provided that
+ * the specified exemption mechanism is enforced.
+ *
+ * @param alg the algorithm name.
+ * @param maxKeySize the maximum allowable key size,
+ * specified in number of bits.
+ * @param algParamSpec the limit for allowable algorithm
+ * parameter spec.
+ * @param exemptionMechanism the name of the exemption
+ * mechanism.
+ */
+ CryptoPermission(String alg,
+ int maxKeySize,
+ AlgorithmParameterSpec algParamSpec,
+ String exemptionMechanism) {
+ super(null);
+ this.alg = alg;
+ this.exemptionMechanism = exemptionMechanism;
+ this.maxKeySize = maxKeySize;
+ this.checkParam = true;
+ this.algParamSpec = algParamSpec;
+ }
+
+ /**
+ * Checks if the specified permission is "implied" by
+ * this object.
+ * <p>
+ * More specifically, this method returns true if:<p>
+ * <ul>
+ * <li> <i>p</i> is an instance of CryptoPermission, and<p>
+ * <li> <i>p</i>'s algorithm name equals or (in the case of wildcards)
+ * is implied by this permission's algorithm name, and<p>
+ * <li> <i>p</i>'s maximum allowable key size is less or
+ * equal to this permission's maximum allowable key size, and<p>
+ * <li> <i>p</i>'s algorithm parameter spec equals or is
+ * implied by this permission's algorithm parameter spec, and<p>
+ * <li> <i>p</i>'s exemptionMechanism equals or
+ * is implied by this permission's
+ * exemptionMechanism (a <code>null</code> exemption mechanism
+ * implies any other exemption mechanism).
+ * </ul>
+ *
+ * @param p the permission to check against.
+ *
+ * @return true if the specified permission is equal to or
+ * implied by this permission, false otherwise.
+ */
+ public boolean implies(Permission p) {
+ if (!(p instanceof CryptoPermission))
+ return false;
+
+ CryptoPermission cp = (CryptoPermission)p;
+
+ if ((!alg.equalsIgnoreCase(cp.alg)) &&
+ (!alg.equalsIgnoreCase(ALG_NAME_WILDCARD))) {
+ return false;
+ }
+
+ // alg is the same as cp's alg or
+ // alg is a wildcard.
+ if (cp.maxKeySize <= this.maxKeySize) {
+ // check algParamSpec.
+ if (!impliesParameterSpec(cp.checkParam, cp.algParamSpec)) {
+ return false;
+ }
+
+ // check exemptionMechanism.
+ if (impliesExemptionMechanism(cp.exemptionMechanism)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks two CryptoPermission objects for equality. Checks that
+ * <code>obj</code> is a CryptoPermission, and has the same
+ * algorithm name,
+ * exemption mechanism name, maximum allowable key size and
+ * algorithm parameter spec
+ * as this object.
+ * <P>
+ * @param obj the object to test for equality with this object.
+ * @return true if <code>obj</code> is equal to this object.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+
+ if (!(obj instanceof CryptoPermission))
+ return false;
+
+ CryptoPermission that = (CryptoPermission) obj;
+
+ if (!(alg.equalsIgnoreCase(that.alg)) ||
+ (maxKeySize != that.maxKeySize)) {
+ return false;
+ }
+ if (this.checkParam != that.checkParam) {
+ return false;
+ }
+ return (equalObjects(this.exemptionMechanism,
+ that.exemptionMechanism) &&
+ equalObjects(this.algParamSpec,
+ that.algParamSpec));
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return a hash code value for this object.
+ */
+
+ public int hashCode() {
+ int retval = alg.hashCode();
+ retval ^= maxKeySize;
+ if (exemptionMechanism != null) {
+ retval ^= exemptionMechanism.hashCode();
+ }
+ if (checkParam) retval ^= 100;
+ if (algParamSpec != null) {
+ retval ^= algParamSpec.hashCode();
+ }
+ return retval;
+ }
+
+ /**
+ * There is no action defined for a CryptoPermission
+ * onject.
+ */
+ public String getActions()
+ {
+ return null;
+ }
+
+ /**
+ * Returns a new PermissionCollection object for storing
+ * CryptoPermission objects.
+ *
+ * @return a new PermissionCollection object suitable for storing
+ * CryptoPermissions.
+ */
+
+ public PermissionCollection newPermissionCollection() {
+ return new CryptoPermissionCollection();
+ }
+
+ /**
+ * Returns the algorithm name associated with
+ * this CryptoPermission object.
+ */
+ final String getAlgorithm() {
+ return alg;
+ }
+
+ /**
+ * Returns the exemption mechanism name
+ * associated with this CryptoPermission
+ * object.
+ */
+ final String getExemptionMechanism() {
+ return exemptionMechanism;
+ }
+
+ /**
+ * Returns the maximum allowable key size associated
+ * with this CryptoPermission object.
+ */
+ final int getMaxKeySize() {
+ return maxKeySize;
+ }
+
+ /**
+ * Returns true if there is a limitation on the
+ * AlgorithmParameterSpec associated with this
+ * CryptoPermission object and false if otherwise.
+ */
+ final boolean getCheckParam() {
+ return checkParam;
+ }
+
+ /**
+ * Returns the AlgorithmParameterSpec
+ * associated with this CryptoPermission
+ * object.
+ */
+ final AlgorithmParameterSpec getAlgorithmParameterSpec() {
+ return algParamSpec;
+ }
+
+ /**
+ * Returns a string describing this CryptoPermission. The convention is to
+ * specify the class name, the algorithm name, the maximum allowable
+ * key size, and the name of the exemption mechanism, in the following
+ * format: '("ClassName" "algorithm" "keysize" "exemption_mechanism")'.
+ *
+ * @return information about this CryptoPermission.
+ */
+ public String toString() {
+ StringBuilder buf = new StringBuilder(100);
+ buf.append("(CryptoPermission " + alg + " " + maxKeySize);
+ if (algParamSpec != null) {
+ if (algParamSpec instanceof RC2ParameterSpec) {
+ buf.append(" , effective " +
+ ((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits());
+ } else if (algParamSpec instanceof RC5ParameterSpec) {
+ buf.append(" , rounds " +
+ ((RC5ParameterSpec)algParamSpec).getRounds());
+ }
+ }
+ if (exemptionMechanism != null) { // OPTIONAL
+ buf.append(" " + exemptionMechanism);
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+
+ private boolean impliesExemptionMechanism(String exemptionMechanism) {
+ if (this.exemptionMechanism == null) {
+ return true;
+ }
+
+ if (exemptionMechanism == null) {
+ return false;
+ }
+
+ if (this.exemptionMechanism.equals(exemptionMechanism)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean impliesParameterSpec(boolean checkParam,
+ AlgorithmParameterSpec algParamSpec) {
+ if ((this.checkParam) && checkParam) {
+ if (algParamSpec == null) {
+ return true;
+ } else if (this.algParamSpec == null) {
+ return false;
+ }
+
+ if (this.algParamSpec.getClass() != algParamSpec.getClass()) {
+ return false;
+ }
+
+ if (algParamSpec instanceof RC2ParameterSpec) {
+ if (((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits() <=
+ ((RC2ParameterSpec)
+ (this.algParamSpec)).getEffectiveKeyBits()) {
+ return true;
+ }
+ }
+
+ if (algParamSpec instanceof RC5ParameterSpec) {
+ if (((RC5ParameterSpec)algParamSpec).getRounds() <=
+ ((RC5ParameterSpec)this.algParamSpec).getRounds()) {
+ return true;
+ }
+ }
+
+ if (algParamSpec instanceof PBEParameterSpec) {
+ if (((PBEParameterSpec)algParamSpec).getIterationCount() <=
+ ((PBEParameterSpec)this.algParamSpec).getIterationCount()) {
+ return true;
+ }
+ }
+
+ // For classes we don't know, the following
+ // may be the best try.
+ if (this.algParamSpec.equals(algParamSpec)) {
+ return true;
+ }
+ return false;
+ } else if (this.checkParam) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private boolean equalObjects(Object obj1, Object obj2) {
+ if (obj1 == null) {
+ return (obj2 == null ? true : false);
+ }
+
+ return obj1.equals(obj2);
+ }
+}
+
+/**
+ * A CryptoPermissionCollection stores a set of CryptoPermission
+ * permissions.
+ *
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.PermissionCollection
+ *
+ * @author Sharon Liu
+ */
+final class CryptoPermissionCollection extends PermissionCollection
+implements Serializable {
+
+ private static final long serialVersionUID = -511215555898802763L;
+
+ private Vector permissions;
+
+ /**
+ * Creates an empty CryptoPermissionCollection
+ * object.
+ */
+ CryptoPermissionCollection() {
+ permissions = new Vector(3);
+ }
+
+ /**
+ * Adds a permission to the CryptoPermissionCollection.
+ *
+ * @param permission the Permission object to add.
+ *
+ * @exception SecurityException - if this CryptoPermissionCollection
+ * object has been marked <i>readOnly</i>.
+ */
+ public void add(Permission permission)
+ {
+ if (isReadOnly())
+ throw new SecurityException("attempt to add a Permission " +
+ "to a readonly PermissionCollection");
+
+ if (!(permission instanceof CryptoPermission))
+ return;
+
+ permissions.addElement(permission);
+ }
+
+ /**
+ * Check and see if this CryptoPermission object implies
+ * the given Permission object.
+ *
+ * @param p the Permission object to compare
+ *
+ * @return true if the given permission is implied by this
+ * CryptoPermissionCollection, false if not.
+ */
+ public boolean implies(Permission permission) {
+ if (!(permission instanceof CryptoPermission))
+ return false;
+
+ CryptoPermission cp = (CryptoPermission)permission;
+
+ Enumeration e = permissions.elements();
+
+ while (e.hasMoreElements()) {
+ CryptoPermission x = (CryptoPermission) e.nextElement();
+ if (x.implies(cp)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all the CryptoPermission objects
+ * in the container.
+ *
+ * @return an enumeration of all the CryptoPermission objects.
+ */
+
+ public Enumeration elements()
+ {
+ return permissions.elements();
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPermissions.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPermissions.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPermissions.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,479 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.NoSuchElementException;
+import java.io.Serializable;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+/**
+ * This class contains CryptoPermission objects, organized into
+ * PermissionCollections according to algorithm names.
+ *
+ * <p>When the <code>add</code> method is called to add a
+ * CryptoPermission, the CryptoPermission is stored in the
+ * appropriate PermissionCollection. If no such
+ * collection exists yet, the algorithm name associated with
+ * the CryptoPermission object is
+ * determined and the <code>newPermissionCollection</code> method
+ * is called on the CryptoPermission or CryptoAllPermission class to
+ * create the PermissionCollection and add it to the Permissions object.
+ *
+ * @see javax.crypto.CryptoPermission
+ * @see java.security.PermissionCollection
+ * @see java.security.Permissions
+ *
+ * @author Sharon Liu
+ * @since 1.4
+ */
+final class CryptoPermissions extends PermissionCollection
+implements Serializable {
+
+ private static final long serialVersionUID = 4946547168093391015L;
+
+ // This class is similar to java.security.Permissions
+ private Hashtable perms;
+
+ /**
+ * Creates a new CryptoPermissions object containing
+ * no CryptoPermissionCollections.
+ */
+ CryptoPermissions() {
+ perms = new Hashtable(7);
+ }
+
+ /**
+ * Populates the crypto policy from the specified
+ * InputStream into this CryptoPermissions object.
+ *
+ * @param in the InputStream to load from.
+ *
+ * @exception SecurityException if cannot load
+ * successfully.
+ */
+ void load(InputStream in)
+ throws IOException, CryptoPolicyParser.ParsingException {
+ CryptoPolicyParser parser = new CryptoPolicyParser();
+ parser.read(new BufferedReader(new InputStreamReader(in, "UTF-8")));
+
+ CryptoPermission[] parsingResult = parser.getPermissions();
+ for (int i = 0; i < parsingResult.length; i++) {
+ this.add(parsingResult[i]);
+ }
+ }
+
+ /**
+ * Returns true if this CryptoPermissions object doesn't
+ * contain any CryptoPermission objects; otherwise, returns
+ * false.
+ */
+ boolean isEmpty() {
+ return perms.isEmpty();
+ }
+
+ /**
+ * Adds a permission object to the PermissionCollection for the
+ * algorithm returned by
+ * <code>(CryptoPermission)permission.getAlgorithm()</code>.
+ *
+ * This method creates
+ * a new PermissionCollection object (and adds the permission to it)
+ * if an appropriate collection does not yet exist. <p>
+ *
+ * @param permission the Permission object to add.
+ *
+ * @exception SecurityException if this CryptoPermissions object is
+ * marked as readonly.
+ *
+ * @see isReadOnly
+ */
+ public void add(Permission permission) {
+
+ if (isReadOnly())
+ throw new SecurityException("Attempt to add a Permission " +
+ "to a readonly CryptoPermissions " +
+ "object");
+
+ if (!(permission instanceof CryptoPermission))
+ return;
+
+ CryptoPermission cryptoPerm = (CryptoPermission)permission;
+ PermissionCollection pc =
+ getPermissionCollection(cryptoPerm);
+ pc.add(cryptoPerm);
+ String alg = cryptoPerm.getAlgorithm();
+ if (!perms.containsKey(alg)) {
+ perms.put(alg, pc);
+ }
+ }
+
+ /**
+ * Checks if this object's PermissionCollection for permissons
+ * of the specified permission's algorithm implies the specified
+ * permission. Returns true if the checking succeeded.
+ *
+ * @param permission the Permission object to check.
+ *
+ * @return true if "permission" is implied by the permissions
+ * in the PermissionCollection it belongs to, false if not.
+ *
+ */
+ public boolean implies(Permission permission) {
+ if (!(permission instanceof CryptoPermission)) {
+ return false;
+ }
+
+ CryptoPermission cryptoPerm = (CryptoPermission)permission;
+
+ PermissionCollection pc =
+ getPermissionCollection(cryptoPerm.getAlgorithm());
+ return pc.implies(cryptoPerm);
+ }
+
+ /**
+ * Returns an enumeration of all the Permission objects in all the
+ * PermissionCollections in this CryptoPermissions object.
+ *
+ * @return an enumeration of all the Permissions.
+ */
+ public Enumeration elements() {
+ // go through each Permissions in the hash table
+ // and call their elements() function.
+ return new PermissionsEnumerator(perms.elements());
+ }
+
+ /**
+ * Returns a CryptoPermissions object which
+ * represents the minimum of the specified
+ * CryptoPermissions object and this
+ * CryptoPermissions object.
+ *
+ * @param other the CryptoPermission
+ * object to compare with this object.
+ */
+ CryptoPermissions getMinimum(CryptoPermissions other) {
+ if (other == null) {
+ return null;
+ }
+
+ if (this.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
+ return other;
+ }
+
+ if (other.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
+ return this;
+ }
+
+ CryptoPermissions ret = new CryptoPermissions();
+
+
+ PermissionCollection thatWildcard =
+ (PermissionCollection)other.perms.get(
+ CryptoPermission.ALG_NAME_WILDCARD);
+ int maxKeySize = 0;
+ if (thatWildcard != null) {
+ maxKeySize = ((CryptoPermission)
+ thatWildcard.elements().nextElement()).getMaxKeySize();
+ }
+ // For each algorithm in this CryptoPermissions,
+ // find out if there is anything we should add into
+ // ret.
+ Enumeration thisKeys = this.perms.keys();
+ while (thisKeys.hasMoreElements()) {
+ String alg = (String)thisKeys.nextElement();
+
+ PermissionCollection thisPc =
+ (PermissionCollection)this.perms.get(alg);
+ PermissionCollection thatPc =
+ (PermissionCollection)other.perms.get(alg);
+
+ CryptoPermission[] partialResult;
+
+ if (thatPc == null) {
+ if (thatWildcard == null) {
+ // The other CryptoPermissions
+ // doesn't allow this given
+ // algorithm at all. Just skip this
+ // algorithm.
+ continue;
+ }
+ partialResult = getMinimum(maxKeySize, thisPc);
+ } else {
+ partialResult = getMinimum(thisPc, thatPc);
+ }
+
+ for (int i = 0; i < partialResult.length; i++) {
+ ret.add(partialResult[i]);
+ }
+ }
+
+ PermissionCollection thisWildcard =
+ (PermissionCollection)this.perms.get(
+ CryptoPermission.ALG_NAME_WILDCARD);
+
+ // If this CryptoPermissions doesn't
+ // have a wildcard, we are done.
+ if (thisWildcard == null) {
+ return ret;
+ }
+
+ // Deal with the algorithms only appear
+ // in the other CryptoPermissions.
+ maxKeySize =
+ ((CryptoPermission)
+ thisWildcard.elements().nextElement()).getMaxKeySize();
+ Enumeration thatKeys = other.perms.keys();
+ while (thatKeys.hasMoreElements()) {
+ String alg = (String)thatKeys.nextElement();
+
+ if (this.perms.containsKey(alg)) {
+ continue;
+ }
+
+ PermissionCollection thatPc =
+ (PermissionCollection)other.perms.get(alg);
+
+ CryptoPermission[] partialResult;
+
+ partialResult = getMinimum(maxKeySize, thatPc);
+
+ for (int i = 0; i < partialResult.length; i++) {
+ ret.add(partialResult[i]);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Get the minimum of the two given PermissionCollection
+ * <code>thisPc</code> and <code>thatPc</code>.
+ *
+ * @param thisPc the first given PermissionColloection
+ * object.
+ *
+ * @param thatPc the second given PermissionCollection
+ * object.
+ */
+ private CryptoPermission[] getMinimum(PermissionCollection thisPc,
+ PermissionCollection thatPc) {
+ Vector permVector = new Vector(2);
+
+ Enumeration thisPcPermissions = thisPc.elements();
+
+ // For each CryptoPermission in
+ // thisPc object, do the following:
+ // 1) if this CryptoPermission is implied
+ // by thatPc, this CryptoPermission
+ // should be returned, and we can
+ // move on to check the next
+ // CryptoPermission in thisPc.
+ // 2) otherwise, we should return
+ // all CryptoPermissions in thatPc
+ // which
+ // are implied by this CryptoPermission.
+ // Then we can move on to the
+ // next CryptoPermission in thisPc.
+ while (thisPcPermissions.hasMoreElements()) {
+ CryptoPermission thisCp =
+ (CryptoPermission)thisPcPermissions.nextElement();
+
+ Enumeration thatPcPermissions = thatPc.elements();
+ while (thatPcPermissions.hasMoreElements()) {
+ CryptoPermission thatCp =
+ (CryptoPermission)thatPcPermissions.nextElement();
+
+ if (thatCp.implies(thisCp)) {
+ permVector.addElement(thisCp);
+ break;
+ }
+ if (thisCp.implies(thatCp)) {
+ permVector.addElement(thatCp);
+ }
+ }
+ }
+
+ CryptoPermission[] ret = new CryptoPermission[permVector.size()];
+ permVector.copyInto(ret);
+ return ret;
+ }
+
+ /**
+ * Returns all the CryptoPermission objects in the given
+ * PermissionCollection object
+ * whose maximum keysize no greater than <code>maxKeySize</code>.
+ * For all CryptoPermission objects with a maximum keysize greater
+ * than <code>maxKeySize</code>, this method constructs a
+ * corresponding CryptoPermission object whose maximum keysize is
+ * set to <code>maxKeySize</code>, and includes that in the result.
+ *
+ * @param maxKeySize the given maximum key size.
+ *
+ * @param pc the given PermissionCollection object.
+ */
+ private CryptoPermission[] getMinimum(int maxKeySize,
+ PermissionCollection pc) {
+ Vector permVector = new Vector(1);
+
+ Enumeration enum_ = pc.elements();
+
+ while (enum_.hasMoreElements()) {
+ CryptoPermission cp =
+ (CryptoPermission)enum_.nextElement();
+ if (cp.getMaxKeySize() <= maxKeySize) {
+ permVector.addElement(cp);
+ } else {
+ if (cp.getCheckParam()) {
+ permVector.addElement(
+ new CryptoPermission(cp.getAlgorithm(),
+ maxKeySize,
+ cp.getAlgorithmParameterSpec(),
+ cp.getExemptionMechanism()));
+ } else {
+ permVector.addElement(
+ new CryptoPermission(cp.getAlgorithm(),
+ maxKeySize,
+ cp.getExemptionMechanism()));
+ }
+ }
+ }
+
+ CryptoPermission[] ret = new CryptoPermission[permVector.size()];
+ permVector.copyInto(ret);
+ return ret;
+ }
+
+ /**
+ * Returns the PermissionCollection for the
+ * specified algorithm. Returns null if there
+ * isn't such a PermissionCollection.
+ *
+ * @param alg the algorithm name.
+ */
+ PermissionCollection getPermissionCollection(String alg) {
+ // If this CryptoPermissions includes CryptoAllPermission,
+ // we should return CryptoAllPermission.
+ if (perms.containsKey(CryptoAllPermission.ALG_NAME)) {
+ return
+ (PermissionCollection)(perms.get(CryptoAllPermission.ALG_NAME));
+ }
+
+ PermissionCollection pc = (PermissionCollection)perms.get(alg);
+
+ // If there isn't a PermissionCollection for
+ // the given algorithm,we should return the
+ // PermissionCollection for the wildcard
+ // if there is one.
+ if (pc == null) {
+ pc = (PermissionCollection)perms.get(
+ CryptoPermission.ALG_NAME_WILDCARD);
+ }
+ return pc;
+ }
+
+ /**
+ * Returns the PermissionCollection for the algorithm
+ * associated with the specified CryptoPermission
+ * object. Creates such a PermissionCollection
+ * if such a PermissionCollection does not
+ * exist yet.
+ *
+ * @param cryptoPerm the CryptoPermission object.
+ */
+ private PermissionCollection getPermissionCollection(
+ CryptoPermission cryptoPerm) {
+
+ String alg = cryptoPerm.getAlgorithm();
+
+ PermissionCollection pc = (PermissionCollection)perms.get(alg);
+
+ if (pc == null) {
+ pc = cryptoPerm.newPermissionCollection();
+ }
+ return pc;
+ }
+}
+
+final class PermissionsEnumerator implements Enumeration {
+
+ // all the perms
+ private Enumeration perms;
+ // the current set
+ private Enumeration permset;
+
+ PermissionsEnumerator(Enumeration e) {
+ perms = e;
+ permset = getNextEnumWithMore();
+ }
+
+ public synchronized boolean hasMoreElements() {
+ // if we enter with permissionimpl null, we know
+ // there are no more left.
+
+ if (permset == null)
+ return false;
+
+ // try to see if there are any left in the current one
+
+ if (permset.hasMoreElements())
+ return true;
+
+ // get the next one that has something in it...
+ permset = getNextEnumWithMore();
+
+ // if it is null, we are done!
+ return (permset != null);
+ }
+
+ public synchronized Object nextElement() {
+ // hasMoreElements will update permset to the next permset
+ // with something in it...
+
+ if (hasMoreElements()) {
+ return permset.nextElement();
+ } else {
+ throw new NoSuchElementException("PermissionsEnumerator");
+ }
+
+ }
+
+ private Enumeration getNextEnumWithMore() {
+ while (perms.hasMoreElements()) {
+ PermissionCollection pc =
+ (PermissionCollection) perms.nextElement();
+ Enumeration next = pc.elements();
+ if (next.hasMoreElements())
+ return next;
+ }
+ return null;
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPolicyParser.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPolicyParser.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/CryptoPolicyParser.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,707 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.io.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.StringTokenizer;
+import static java.util.Locale.ENGLISH;
+
+import java.security.GeneralSecurityException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.lang.reflect.*;
+
+/**
+ * JCE has two pairs of jurisdiction policy files: one represents U.S. export
+ * laws, and the other represents the local laws of the country where the
+ * JCE will be used.
+ *
+ * The jurisdiction policy file has the same syntax as JDK policy files except
+ * that JCE has new permission classes called javax.crypto.CryptoPermission
+ * and javax.crypto.CryptoAllPermission.
+ *
+ * The format of a permission entry in the jurisdiction policy file is:
+ *
+ * permission <crypto permission class name>[, <algorithm name>
+ * [[, <exemption mechanism name>][, <maxKeySize>
+ * [, <AlgrithomParameterSpec class name>, <parameters
+ * for constructing an AlgrithomParameterSpec object>]]]];
+ *
+ * @author Sharon Liu
+ *
+ * @see java.security.Permissions
+ * @see java.security.spec.AlgrithomParameterSpec
+ * @see javax.crypto.CryptoPermission
+ * @see javax.crypto.CryptoAllPermission
+ * @see javax.crypto.CryptoPermissions
+ * @since 1.4
+ */
+
+final class CryptoPolicyParser {
+
+ private Vector grantEntries;
+
+ // Convenience variables for parsing
+ private StreamTokenizer st;
+ private int lookahead;
+
+ /**
+ * Creates a CryptoPolicyParser object.
+ */
+ CryptoPolicyParser() {
+ grantEntries = new Vector();
+ }
+
+ /**
+ * Reads a policy configuration using a Reader object. <p>
+ *
+ * @param policy the policy Reader object.
+ *
+ * @exception ParsingException if the policy configuration
+ * contains a syntax error.
+ *
+ * @exception IOException if an error occurs while reading
+ * the policy configuration.
+ */
+
+ void read(Reader policy)
+ throws ParsingException, IOException
+ {
+ if (!(policy instanceof BufferedReader)) {
+ policy = new BufferedReader(policy);
+ }
+
+ /*
+ * Configure the stream tokenizer:
+ * Recognize strings between "..."
+ * Don't convert words to lowercase
+ * Recognize both C-style and C++-style comments
+ * Treat end-of-line as white space, not as a token
+ */
+ st = new StreamTokenizer(policy);
+
+ st.resetSyntax();
+ st.wordChars('a', 'z');
+ st.wordChars('A', 'Z');
+ st.wordChars('.', '.');
+ st.wordChars('0', '9');
+ st.wordChars('_', '_');
+ st.wordChars('$', '$');
+ st.wordChars(128 + 32, 255);
+ st.whitespaceChars(0, ' ');
+ st.commentChar('/');
+ st.quoteChar('\'');
+ st.quoteChar('"');
+ st.lowerCaseMode(false);
+ st.ordinaryChar('/');
+ st.slashSlashComments(true);
+ st.slashStarComments(true);
+ st.parseNumbers();
+
+ /*
+ * The crypto jurisdiction policy must be consistent. The
+ * following hashtable is used for checking consistency.
+ */
+ Hashtable processedPermissions = null;
+
+ /*
+ * The main parsing loop. The loop is executed once for each entry
+ * in the policy file. The entries are delimited by semicolons. Once
+ * we've read in the information for an entry, go ahead and try to
+ * add it to the grantEntries.
+ */
+ lookahead = st.nextToken();
+ while (lookahead != StreamTokenizer.TT_EOF) {
+ if (peek("grant")) {
+ GrantEntry ge = parseGrantEntry(processedPermissions);
+ if (ge != null)
+ grantEntries.addElement(ge);
+ } else {
+ throw new ParsingException(st.lineno(), "expected grant " +
+ "statement");
+ }
+ match(";");
+ }
+ }
+
+ /**
+ * parse a Grant entry
+ */
+ private GrantEntry parseGrantEntry(Hashtable processedPermissions)
+ throws ParsingException, IOException
+ {
+ GrantEntry e = new GrantEntry();
+
+ match("grant");
+ match("{");
+
+ while(!peek("}")) {
+ if (peek("Permission")) {
+ CryptoPermissionEntry pe =
+ parsePermissionEntry(processedPermissions);
+ e.add(pe);
+ match(";");
+ } else {
+ throw new
+ ParsingException(st.lineno(), "expected permission entry");
+ }
+ }
+ match("}");
+
+ return e;
+ }
+
+ /**
+ * parse a CryptoPermission entry
+ */
+ private CryptoPermissionEntry parsePermissionEntry(
+ Hashtable processedPermissions)
+ throws ParsingException, IOException
+ {
+ CryptoPermissionEntry e = new CryptoPermissionEntry();
+
+ match("Permission");
+ e.cryptoPermission = match("permission type");
+
+ if (e.cryptoPermission.equals("javax.crypto.CryptoAllPermission")) {
+ // Done with the CryptoAllPermission entry.
+ e.alg = CryptoAllPermission.ALG_NAME;
+ e.maxKeySize = Integer.MAX_VALUE;
+ return e;
+ }
+
+ // Should see the algorithm name.
+ if (peek("\"")) {
+ // Algorithm name - always convert to upper case after parsing.
+ e.alg = match("quoted string").toUpperCase(ENGLISH);
+ } else {
+ // The algorithm name can be a wildcard.
+ if (peek("*")) {
+ match("*");
+ e.alg = CryptoPermission.ALG_NAME_WILDCARD;
+ } else {
+ throw new ParsingException(st.lineno(),
+ "Missing the algorithm name");
+ }
+ }
+
+ peekAndMatch(",");
+
+ // May see the exemption mechanism name.
+ if (peek("\"")) {
+ // Exemption mechanism name - convert to upper case too.
+ e.exemptionMechanism = match("quoted string").toUpperCase(ENGLISH);
+ }
+
+ peekAndMatch(",");
+
+ // Check whether this entry is consistent with other permission entries
+ // that have been read.
+ if (!isConsistent(e.alg, e.exemptionMechanism, processedPermissions)) {
+ throw new ParsingException(st.lineno(), "Inconsistent policy");
+ }
+
+ // Should see the maxKeySize if not at the end of this entry yet.
+ if (peek("number")) {
+ e.maxKeySize = match();
+ } else {
+ if (peek("*")) {
+ match("*");
+ e.maxKeySize = Integer.MAX_VALUE;
+ } else {
+ if (!peek(";")) {
+ throw new ParsingException(st.lineno(),
+ "Missing the maximum " +
+ "allowable key size");
+ } else {
+ // At the end of this permission entry
+ e.maxKeySize = Integer.MAX_VALUE;
+ }
+ }
+ }
+
+ peekAndMatch(",");
+
+ // May see an AlgorithmParameterSpec class name.
+ if (peek("\"")) {
+ // AlgorithmParameterSpec class name.
+ String algParamSpecClassName = match("quoted string");
+
+ Vector paramsV = new Vector(1);
+ while (peek(",")) {
+ match(",");
+ if (peek("number")) {
+ paramsV.addElement(new Integer(match()));
+ } else {
+ if (peek("*")) {
+ match("*");
+ paramsV.addElement(new Integer(Integer.MAX_VALUE));
+ } else {
+ throw new ParsingException(st.lineno(),
+ "Expecting an integer");
+ }
+ }
+ }
+
+ Integer[] params = new Integer[paramsV.size()];
+ paramsV.copyInto(params);
+
+ e.checkParam = true;
+ e.algParamSpec = getInstance(algParamSpecClassName, params);
+ }
+
+ return e;
+ }
+
+ private static final AlgorithmParameterSpec getInstance(String type,
+ Integer[] params)
+ throws ParsingException
+ {
+ AlgorithmParameterSpec ret = null;
+
+ try {
+ Class apsClass = Class.forName(type);
+ Class[] paramClasses = new Class[params.length];
+
+ for (int i = 0; i < params.length; i++) {
+ paramClasses[i] = int.class;
+ }
+
+ Constructor c = apsClass.getConstructor(paramClasses);
+ ret = (AlgorithmParameterSpec) c.newInstance((Object[]) params);
+ } catch (Exception e) {
+ throw new ParsingException("Cannot call the constructor of " +
+ type + e);
+ }
+ return ret;
+ }
+
+
+ private boolean peekAndMatch(String expect)
+ throws ParsingException, IOException
+ {
+ if (peek(expect)) {
+ match(expect);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean peek(String expect) {
+ boolean found = false;
+
+ switch (lookahead) {
+
+ case StreamTokenizer.TT_WORD:
+ if (expect.equalsIgnoreCase(st.sval))
+ found = true;
+ break;
+ case StreamTokenizer.TT_NUMBER:
+ if (expect.equalsIgnoreCase("number")) {
+ found = true;
+ }
+ break;
+ case ',':
+ if (expect.equals(","))
+ found = true;
+ break;
+ case '{':
+ if (expect.equals("{"))
+ found = true;
+ break;
+ case '}':
+ if (expect.equals("}"))
+ found = true;
+ break;
+ case '"':
+ if (expect.equals("\""))
+ found = true;
+ break;
+ case '*':
+ if (expect.equals("*"))
+ found = true;
+ break;
+ case ';':
+ if (expect.equals(";"))
+ found = true;
+ break;
+ default:
+ break;
+ }
+ return found;
+ }
+
+ /**
+ * Excepts to match a non-negative number.
+ */
+ private int match()
+ throws ParsingException, IOException
+ {
+ int value = -1;
+ int lineno = st.lineno();
+ String sValue = null;
+
+ switch (lookahead) {
+ case StreamTokenizer.TT_NUMBER:
+ value = (int)st.nval;
+ if (value < 0) {
+ sValue = String.valueOf(st.nval);
+ }
+ lookahead = st.nextToken();
+ break;
+ default:
+ sValue = st.sval;
+ break;
+ }
+ if (value <= 0) {
+ throw new ParsingException(lineno, "a non-negative number",
+ sValue);
+ }
+ return value;
+ }
+
+ private String match(String expect)
+ throws ParsingException, IOException
+ {
+ String value = null;
+
+ switch (lookahead) {
+ case StreamTokenizer.TT_NUMBER:
+ throw new ParsingException(st.lineno(), expect,
+ "number "+String.valueOf(st.nval));
+ case StreamTokenizer.TT_EOF:
+ throw new ParsingException("expected "+expect+", read end of file");
+ case StreamTokenizer.TT_WORD:
+ if (expect.equalsIgnoreCase(st.sval)) {
+ lookahead = st.nextToken();
+ }
+ else if (expect.equalsIgnoreCase("permission type")) {
+ value = st.sval;
+ lookahead = st.nextToken();
+ }
+ else
+ throw new ParsingException(st.lineno(), expect, st.sval);
+ break;
+ case '"':
+ if (expect.equalsIgnoreCase("quoted string")) {
+ value = st.sval;
+ lookahead = st.nextToken();
+ } else if (expect.equalsIgnoreCase("permission type")) {
+ value = st.sval;
+ lookahead = st.nextToken();
+ }
+ else
+ throw new ParsingException(st.lineno(), expect, st.sval);
+ break;
+ case ',':
+ if (expect.equals(","))
+ lookahead = st.nextToken();
+ else
+ throw new ParsingException(st.lineno(), expect, ",");
+ break;
+ case '{':
+ if (expect.equals("{"))
+ lookahead = st.nextToken();
+ else
+ throw new ParsingException(st.lineno(), expect, "{");
+ break;
+ case '}':
+ if (expect.equals("}"))
+ lookahead = st.nextToken();
+ else
+ throw new ParsingException(st.lineno(), expect, "}");
+ break;
+ case ';':
+ if (expect.equals(";"))
+ lookahead = st.nextToken();
+ else
+ throw new ParsingException(st.lineno(), expect, ";");
+ break;
+ case '*':
+ if (expect.equals("*"))
+ lookahead = st.nextToken();
+ else
+ throw new ParsingException(st.lineno(), expect, "*");
+ break;
+ default:
+ throw new ParsingException(st.lineno(), expect,
+ new String(new char[] {(char)lookahead}));
+ }
+ return value;
+ }
+
+ CryptoPermission[] getPermissions() {
+ Vector result = new Vector();
+
+ Enumeration grantEnum = grantEntries.elements();
+ while (grantEnum.hasMoreElements()) {
+ GrantEntry ge = (GrantEntry)grantEnum.nextElement();
+ Enumeration permEnum = ge.permissionElements();
+ while (permEnum.hasMoreElements()) {
+ CryptoPermissionEntry pe =
+ (CryptoPermissionEntry)permEnum.nextElement();
+ if (pe.cryptoPermission.equals(
+ "javax.crypto.CryptoAllPermission")) {
+ result.addElement(CryptoAllPermission.INSTANCE);
+ } else {
+ if (pe.checkParam) {
+ result.addElement(new CryptoPermission(
+ pe.alg,
+ pe.maxKeySize,
+ pe.algParamSpec,
+ pe.exemptionMechanism));
+ } else {
+ result.addElement(new CryptoPermission(
+ pe.alg,
+ pe.maxKeySize,
+ pe.exemptionMechanism));
+ }
+ }
+ }
+ }
+
+ CryptoPermission[] ret = new CryptoPermission[result.size()];
+ result.copyInto(ret);
+
+ return ret;
+ }
+
+ private boolean isConsistent(String alg,
+ String exemptionMechanism,
+ Hashtable processedPermissions) {
+ String thisExemptionMechanism =
+ exemptionMechanism == null ? "none" : exemptionMechanism;
+
+ if (processedPermissions == null) {
+ processedPermissions = new Hashtable();
+ Vector exemptionMechanisms = new Vector(1);
+ exemptionMechanisms.addElement(thisExemptionMechanism);
+ processedPermissions.put(alg, exemptionMechanisms);
+ return true;
+ }
+
+ if (processedPermissions.containsKey(CryptoAllPermission.ALG_NAME)) {
+ return false;
+ }
+
+ Vector exemptionMechanisms;
+
+ if (processedPermissions.containsKey(alg)) {
+ exemptionMechanisms = (Vector)processedPermissions.get(alg);
+ if (exemptionMechanisms.contains(thisExemptionMechanism)) {
+ return false;
+ }
+ } else {
+ exemptionMechanisms = new Vector(1);
+ }
+
+ exemptionMechanisms.addElement(thisExemptionMechanism);
+ processedPermissions.put(alg, exemptionMechanisms);
+ return true;
+ }
+
+ /**
+ * Each grant entry in the policy configuration file is represented by a
+ * GrantEntry object. <p>
+ *
+ * <p>
+ * For example, the entry
+ * <pre>
+ * grant {
+ * permission javax.crypto.CryptoPermission "DES", 56;
+ * };
+ *
+ * </pre>
+ * is represented internally
+ * <pre>
+ *
+ * pe = new CryptoPermissionEntry("javax.crypto.CryptoPermission",
+ * "DES", 56);
+ *
+ * ge = new GrantEntry();
+ *
+ * ge.add(pe);
+ *
+ * </pre>
+ *
+ * @see java.security.Permission
+ * @see javax.crypto.CryptoPermission
+ * @see javax.crypto.CryptoPermissions
+ */
+
+ private static class GrantEntry {
+
+ private Vector permissionEntries;
+
+ GrantEntry() {
+ permissionEntries = new Vector();
+ }
+
+ void add(CryptoPermissionEntry pe)
+ {
+ permissionEntries.addElement(pe);
+ }
+
+ boolean remove(CryptoPermissionEntry pe)
+ {
+ return permissionEntries.removeElement(pe);
+ }
+
+ boolean contains(CryptoPermissionEntry pe)
+ {
+ return permissionEntries.contains(pe);
+ }
+
+ /**
+ * Enumerate all the permission entries in this GrantEntry.
+ */
+ Enumeration permissionElements(){
+ return permissionEntries.elements();
+ }
+
+ }
+
+ /**
+ * Each crypto permission entry in the policy configuration file is
+ * represented by a CryptoPermissionEntry object. <p>
+ *
+ * <p>
+ * For example, the entry
+ * <pre>
+ * permission javax.crypto.CryptoPermission "DES", 56;
+ * </pre>
+ * is represented internally
+ * <pre>
+ *
+ * pe = new CryptoPermissionEntry("javax.crypto.cryptoPermission",
+ * "DES", 56);
+ * </pre>
+ *
+ * @see java.security.Permissions
+ * @see javax.crypto.CryptoPermission
+ * @see javax.crypto.CryptoAllPermission
+ */
+
+ private static class CryptoPermissionEntry {
+
+ String cryptoPermission;
+ String alg;
+ String exemptionMechanism;
+ int maxKeySize;
+ boolean checkParam;
+ AlgorithmParameterSpec algParamSpec;
+
+ CryptoPermissionEntry() {
+ // Set default values.
+ maxKeySize = 0;
+ alg = null;
+ exemptionMechanism = null;
+ checkParam = false;
+ algParamSpec = null;
+ }
+
+ /**
+ * Calculates a hash code value for the object. Objects
+ * which are equal will also have the same hashcode.
+ */
+ public int hashCode() {
+ int retval = cryptoPermission.hashCode();
+ if (alg != null) retval ^= alg.hashCode();
+ if (exemptionMechanism != null) {
+ retval ^= exemptionMechanism.hashCode();
+ }
+ retval ^= maxKeySize;
+ if (checkParam) retval ^= 100;
+ if (algParamSpec != null) {
+ retval ^= algParamSpec.hashCode();
+ }
+ return retval;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+
+ if (!(obj instanceof CryptoPermissionEntry))
+ return false;
+
+ CryptoPermissionEntry that = (CryptoPermissionEntry) obj;
+
+ if (this.cryptoPermission == null) {
+ if (that.cryptoPermission != null) return false;
+ } else {
+ if (!this.cryptoPermission.equals(
+ that.cryptoPermission))
+ return false;
+ }
+
+ if (this.alg == null) {
+ if (that.alg != null) return false;
+ } else {
+ if (!this.alg.equalsIgnoreCase(that.alg))
+ return false;
+ }
+
+ if (!(this.maxKeySize == that.maxKeySize)) return false;
+
+ if (this.checkParam != that.checkParam) return false;
+
+ if (this.algParamSpec == null) {
+ if (that.algParamSpec != null) return false;
+ } else {
+ if (!this.algParamSpec.equals(that.algParamSpec))
+ return false;
+ }
+
+ // everything matched -- the 2 objects are equal
+ return true;
+ }
+ }
+
+ static final class ParsingException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 7147241245566588374L;
+
+ /**
+ * Constructs a ParsingException with the specified
+ * detail message.
+ * @param msg the detail message.
+ */
+ ParsingException(String msg) {
+ super(msg);
+ }
+
+ ParsingException(int line, String msg) {
+ super("line " + line + ": " + msg);
+ }
+
+ ParsingException(int line, String expect, String actual) {
+ super("line "+line+": expected '"+expect+"', found '"+actual+"'");
+ }
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,448 @@
+/*
+ * Copyright 2001-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.io.*;
+import java.security.*;
+import java.security.spec.*;
+import sun.security.x509.AlgorithmId;
+import sun.security.util.DerValue;
+import sun.security.util.DerInputStream;
+import sun.security.util.DerOutputStream;
+
+/**
+ * This class implements the <code>EncryptedPrivateKeyInfo</code> type
+ * as defined in PKCS #8.
+ * <p>Its ASN.1 definition is as follows:
+ *
+ * <pre>
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ * encryptionAlgorithm AlgorithmIdentifier,
+ * encryptedData OCTET STRING }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * </pre>
+ *
+ * @author Valerie Peng
+ *
+ * @see java.security.spec.PKCS8EncodedKeySpec
+ *
+ * @since 1.4
+ */
+
+public class EncryptedPrivateKeyInfo {
+
+ // the "encryptionAlgorithm" field
+ private AlgorithmId algid;
+
+ // the "encryptedData" field
+ private byte[] encryptedData;
+
+ // the ASN.1 encoded contents of this class
+ private byte[] encoded = null;
+
+ /**
+ * Constructs (i.e., parses) an <code>EncryptedPrivateKeyInfo</code> from
+ * its ASN.1 encoding.
+ * @param encoded the ASN.1 encoding of this object. The contents of
+ * the array are copied to protect against subsequent modification.
+ * @exception NullPointerException if the <code>encoded</code> is null.
+ * @exception IOException if error occurs when parsing the ASN.1 encoding.
+ */
+ public EncryptedPrivateKeyInfo(byte[] encoded)
+ throws IOException {
+ if (encoded == null) {
+ throw new NullPointerException("the encoded parameter " +
+ "must be non-null");
+ }
+ this.encoded = (byte[])encoded.clone();
+ DerValue val = new DerValue(this.encoded);
+
+ DerValue[] seq = new DerValue[2];
+
+ seq[0] = val.data.getDerValue();
+ seq[1] = val.data.getDerValue();
+
+ if (val.data.available() != 0) {
+ throw new IOException("overrun, bytes = " + val.data.available());
+ }
+
+ this.algid = AlgorithmId.parse(seq[0]);
+ if (seq[0].data.available() != 0) {
+ throw new IOException("encryptionAlgorithm field overrun");
+ }
+
+ this.encryptedData = seq[1].getOctetString();
+ if (seq[1].data.available() != 0) {
+ throw new IOException("encryptedData field overrun");
+ }
+ }
+
+ /**
+ * Constructs an <code>EncryptedPrivateKeyInfo</code> from the
+ * encryption algorithm name and the encrypted data.
+ *
+ * <p>Note: This constructor will use null as the value of the
+ * algorithm parameters. If the encryption algorithm has
+ * parameters whose value is not null, a different constructor,
+ * e.g. EncryptedPrivateKeyInfo(AlgorithmParameters, byte[]),
+ * should be used.
+ *
+ * @param algName encryption algorithm name. See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard Cipher algorithm names.
+ * @param encryptedData encrypted data. The contents of
+ * <code>encrypedData</code> are copied to protect against subsequent
+ * modification when constructing this object.
+ * @exception NullPointerException if <code>algName</code> or
+ * <code>encryptedData</code> is null.
+ * @exception IllegalArgumentException if <code>encryptedData</code>
+ * is empty, i.e. 0-length.
+ * @exception NoSuchAlgorithmException if the specified algName is
+ * not supported.
+ */
+ public EncryptedPrivateKeyInfo(String algName, byte[] encryptedData)
+ throws NoSuchAlgorithmException {
+
+ if (algName == null)
+ throw new NullPointerException("the algName parameter " +
+ "must be non-null");
+ this.algid = AlgorithmId.get(algName);
+
+ if (encryptedData == null) {
+ throw new NullPointerException("the encryptedData " +
+ "parameter must be non-null");
+ } else if (encryptedData.length == 0) {
+ throw new IllegalArgumentException("the encryptedData " +
+ "parameter must not be empty");
+ } else {
+ this.encryptedData = (byte[])encryptedData.clone();
+ }
+ // delay the generation of ASN.1 encoding until
+ // getEncoded() is called
+ this.encoded = null;
+ }
+
+ /**
+ * Constructs an <code>EncryptedPrivateKeyInfo</code> from the
+ * encryption algorithm parameters and the encrypted data.
+ *
+ * @param algParams the algorithm parameters for the encryption
+ * algorithm. <code>algParams.getEncoded()</code> should return
+ * the ASN.1 encoded bytes of the <code>parameters</code> field
+ * of the <code>AlgorithmIdentifer</code> component of the
+ * <code>EncryptedPrivateKeyInfo</code> type.
+ * @param encryptedData encrypted data. The contents of
+ * <code>encrypedData</code> are copied to protect against
+ * subsequent modification when constructing this object.
+ * @exception NullPointerException if <code>algParams</code> or
+ * <code>encryptedData</code> is null.
+ * @exception IllegalArgumentException if <code>encryptedData</code>
+ * is empty, i.e. 0-length.
+ * @exception NoSuchAlgorithmException if the specified algName of
+ * the specified <code>algParams</code> parameter is not supported.
+ */
+ public EncryptedPrivateKeyInfo(AlgorithmParameters algParams,
+ byte[] encryptedData) throws NoSuchAlgorithmException {
+
+ if (algParams == null) {
+ throw new NullPointerException("algParams must be non-null");
+ }
+ this.algid = AlgorithmId.get(algParams);
+
+ if (encryptedData == null) {
+ throw new NullPointerException("encryptedData must be non-null");
+ } else if (encryptedData.length == 0) {
+ throw new IllegalArgumentException("the encryptedData " +
+ "parameter must not be empty");
+ } else {
+ this.encryptedData = (byte[])encryptedData.clone();
+ }
+
+ // delay the generation of ASN.1 encoding until
+ // getEncoded() is called
+ this.encoded = null;
+ }
+
+
+ /**
+ * Returns the encryption algorithm.
+ * <p>Note: Standard name is returned instead of the specified one
+ * in the constructor when such mapping is available.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard Cipher algorithm names.
+ *
+ * @return the encryption algorithm name.
+ */
+ public String getAlgName() {
+ return this.algid.getName();
+ }
+
+ /**
+ * Returns the algorithm parameters used by the encryption algorithm.
+ * @return the algorithm parameters.
+ */
+ public AlgorithmParameters getAlgParameters() {
+ return this.algid.getParameters();
+ }
+
+ /**
+ * Returns the encrypted data.
+ * @return the encrypted data. Returns a new array
+ * each time this method is called.
+ */
+ public byte[] getEncryptedData() {
+ return (byte[])this.encryptedData.clone();
+ }
+
+ /**
+ * Extract the enclosed PKCS8EncodedKeySpec object from the
+ * encrypted data and return it.
+ * <br>Note: In order to successfully retrieve the enclosed
+ * PKCS8EncodedKeySpec object, <code>cipher</code> needs
+ * to be initialized to either Cipher.DECRYPT_MODE or
+ * Cipher.UNWRAP_MODE, with the same key and parameters used
+ * for generating the encrypted data.
+ *
+ * @param cipher the initialized cipher object which will be
+ * used for decrypting the encrypted data.
+ * @return the PKCS8EncodedKeySpec object.
+ * @exception NullPointerException if <code>cipher</code>
+ * is null.
+ * @exception InvalidKeySpecException if the given cipher is
+ * inappropriate for the encrypted data or the encrypted
+ * data is corrupted and cannot be decrypted.
+ */
+ public PKCS8EncodedKeySpec getKeySpec(Cipher cipher)
+ throws InvalidKeySpecException {
+ byte[] encoded = null;
+ try {
+ encoded = cipher.doFinal((byte[])encryptedData);
+ checkPKCS8Encoding(encoded);
+ } catch (GeneralSecurityException gse) {
+ InvalidKeySpecException ikse = new
+ InvalidKeySpecException(
+ "Cannot retrieve the PKCS8EncodedKeySpec");
+ ikse.initCause(gse);
+ throw ikse;
+ } catch (IOException ioe) {
+ InvalidKeySpecException ikse = new
+ InvalidKeySpecException(
+ "Cannot retrieve the PKCS8EncodedKeySpec");
+ ikse.initCause(ioe);
+ throw ikse;
+ } catch (IllegalStateException ise) {
+ InvalidKeySpecException ikse = new
+ InvalidKeySpecException(
+ "Cannot retrieve the PKCS8EncodedKeySpec");
+ ikse.initCause(ise);
+ throw ikse;
+ }
+ return new PKCS8EncodedKeySpec(encoded);
+ }
+
+ private PKCS8EncodedKeySpec getKeySpecImpl(Key decryptKey,
+ Provider provider) throws NoSuchAlgorithmException,
+ InvalidKeyException {
+ byte[] encoded = null;
+ Cipher c;
+ try {
+ if (provider == null) {
+ // use the most preferred one
+ c = Cipher.getInstance(algid.getName());
+ } else {
+ c = Cipher.getInstance(algid.getName(), provider);
+ }
+ c.init(Cipher.DECRYPT_MODE, decryptKey, algid.getParameters());
+ encoded = c.doFinal(encryptedData);
+ checkPKCS8Encoding(encoded);
+ } catch (NoSuchAlgorithmException nsae) {
+ // rethrow
+ throw nsae;
+ } catch (GeneralSecurityException gse) {
+ InvalidKeyException ike = new InvalidKeyException
+ ("Cannot retrieve the PKCS8EncodedKeySpec");
+ ike.initCause(gse);
+ throw ike;
+ } catch (IOException ioe) {
+ InvalidKeyException ike = new InvalidKeyException
+ ("Cannot retrieve the PKCS8EncodedKeySpec");
+ ike.initCause(ioe);
+ throw ike;
+ }
+ return new PKCS8EncodedKeySpec(encoded);
+ }
+
+ /**
+ * Extract the enclosed PKCS8EncodedKeySpec object from the
+ * encrypted data and return it.
+ * @param decryptKey key used for decrypting the encrypted data.
+ * @return the PKCS8EncodedKeySpec object.
+ * @exception NullPointerException if <code>decryptKey</code>
+ * is null.
+ * @exception NoSuchAlgorithmException if cannot find appropriate
+ * cipher to decrypt the encrypted data.
+ * @exception InvalidKeyException if <code>decryptKey</code>
+ * cannot be used to decrypt the encrypted data or the decryption
+ * result is not a valid PKCS8KeySpec.
+ *
+ * @since 1.5
+ */
+ public PKCS8EncodedKeySpec getKeySpec(Key decryptKey)
+ throws NoSuchAlgorithmException, InvalidKeyException {
+ if (decryptKey == null) {
+ throw new NullPointerException("decryptKey is null");
+ }
+ return getKeySpecImpl(decryptKey, null);
+ }
+
+ /**
+ * Extract the enclosed PKCS8EncodedKeySpec object from the
+ * encrypted data and return it.
+ * @param decryptKey key used for decrypting the encrypted data.
+ * @param providerName the name of provider whose Cipher
+ * implementation will be used.
+ * @return the PKCS8EncodedKeySpec object.
+ * @exception NullPointerException if <code>decryptKey</code>
+ * or <code>providerName</code> is null.
+ * @exception NoSuchProviderException if no provider
+ * <code>providerName</code> is registered.
+ * @exception NoSuchAlgorithmException if cannot find appropriate
+ * cipher to decrypt the encrypted data.
+ * @exception InvalidKeyException if <code>decryptKey</code>
+ * cannot be used to decrypt the encrypted data or the decryption
+ * result is not a valid PKCS8KeySpec.
+ *
+ * @since 1.5
+ */
+ public PKCS8EncodedKeySpec getKeySpec(Key decryptKey,
+ String providerName) throws NoSuchProviderException,
+ NoSuchAlgorithmException, InvalidKeyException {
+ if (decryptKey == null) {
+ throw new NullPointerException("decryptKey is null");
+ }
+ if (providerName == null) {
+ throw new NullPointerException("provider is null");
+ }
+ Provider provider = Security.getProvider(providerName);
+ if (provider == null) {
+ throw new NoSuchProviderException("provider " +
+ providerName + " not found");
+ }
+ return getKeySpecImpl(decryptKey, provider);
+ }
+
+ /**
+ * Extract the enclosed PKCS8EncodedKeySpec object from the
+ * encrypted data and return it.
+ * @param decryptKey key used for decrypting the encrypted data.
+ * @param provider the name of provider whose Cipher implementation
+ * will be used.
+ * @return the PKCS8EncodedKeySpec object.
+ * @exception NullPointerException if <code>decryptKey</code>
+ * or <code>provider</code> is null.
+ * @exception NoSuchAlgorithmException if cannot find appropriate
+ * cipher to decrypt the encrypted data in <code>provider</code>.
+ * @exception InvalidKeyException if <code>decryptKey</code>
+ * cannot be used to decrypt the encrypted data or the decryption
+ * result is not a valid PKCS8KeySpec.
+ *
+ * @since 1.5
+ */
+ public PKCS8EncodedKeySpec getKeySpec(Key decryptKey,
+ Provider provider) throws NoSuchAlgorithmException,
+ InvalidKeyException {
+ if (decryptKey == null) {
+ throw new NullPointerException("decryptKey is null");
+ }
+ if (provider == null) {
+ throw new NullPointerException("provider is null");
+ }
+ return getKeySpecImpl(decryptKey, provider);
+ }
+
+ /**
+ * Returns the ASN.1 encoding of this object.
+ * @return the ASN.1 encoding. Returns a new array
+ * each time this method is called.
+ * @exception IOException if error occurs when constructing its
+ * ASN.1 encoding.
+ */
+ public byte[] getEncoded() throws IOException {
+ if (this.encoded == null) {
+ DerOutputStream out = new DerOutputStream();
+ DerOutputStream tmp = new DerOutputStream();
+
+ // encode encryption algorithm
+ algid.encode(tmp);
+
+ // encode encrypted data
+ tmp.putOctetString(encryptedData);
+
+ // wrap everything into a SEQUENCE
+ out.write(DerValue.tag_Sequence, tmp);
+ this.encoded = out.toByteArray();
+ }
+ return (byte[])this.encoded.clone();
+ }
+
+ private static void checkTag(DerValue val, byte tag, String valName)
+ throws IOException {
+ if (val.getTag() != tag) {
+ throw new IOException("invalid key encoding - wrong tag for " +
+ valName);
+ }
+ }
+
+ private static void checkPKCS8Encoding(byte[] encodedKey)
+ throws IOException {
+ DerInputStream in = new DerInputStream(encodedKey);
+ DerValue[] values = in.getSequence(3);
+
+ switch (values.length) {
+ case 4:
+ checkTag(values[3], DerValue.TAG_CONTEXT, "attributes");
+ case 3:
+ checkTag(values[0], DerValue.tag_Integer, "version");
+ DerInputStream algid = values[1].toDerInputStream();
+ algid.getOID();
+ if (algid.available() != 0) {
+ algid.getDerValue();
+ }
+ checkTag(values[2], DerValue.tag_OctetString, "privateKey");
+ break;
+ default:
+ throw new IOException("invalid key encoding");
+ }
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanism.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanism.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanism.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,486 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.AlgorithmParameters;
+import java.security.Provider;
+import java.security.Key;
+import java.security.Security;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.AlgorithmParameterSpec;
+
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class provides the functionality of an exemption mechanism, examples
+ * of which are <i>key recovery</i>, <i>key weakening</i>, and
+ * <i>key escrow</i>.
+ *
+ * <p>Applications or applets that use an exemption mechanism may be granted
+ * stronger encryption capabilities than those which don't.
+ *
+ * @since 1.4
+ */
+
+public class ExemptionMechanism {
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation (delegate)
+ private ExemptionMechanismSpi exmechSpi;
+
+ // The name of the exemption mechanism.
+ private String mechanism;
+
+ // Flag which indicates whether this ExemptionMechanism
+ // result is generated successfully.
+ private boolean done = false;
+
+ // State information
+ private boolean initialized = false;
+
+ // Store away the key at init() time for later comparison.
+ private Key keyStored = null;
+
+ /**
+ * Creates a ExemptionMechanism object.
+ *
+ * @param exmechSpi the delegate
+ * @param provider the provider
+ * @param mechanism the exemption mechanism
+ */
+ protected ExemptionMechanism(ExemptionMechanismSpi exmechSpi,
+ Provider provider,
+ String mechanism) {
+ this.exmechSpi = exmechSpi;
+ this.provider = provider;
+ this.mechanism = mechanism;
+ }
+
+ /**
+ * Returns the exemption mechanism name of this
+ * <code>ExemptionMechanism</code> object.
+ *
+ * <p>This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this
+ * <code>ExemptionMechanism</code> object.
+ *
+ * @return the exemption mechanism name of this
+ * <code>ExemptionMechanism</code> object.
+ */
+ public final String getName() {
+ return this.mechanism;
+ }
+
+ /**
+ * Returns an <code>ExemptionMechanism</code> object that implements the
+ * specified exemption mechanism algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new ExemptionMechanism object encapsulating the
+ * ExemptionMechanismSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested exemption
+ * mechanism.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard exemption mechanism names.
+ *
+ * @return the new <code>ExemptionMechanism</code> object.
+ *
+ * @exception NullPointerException if <code>algorithm</code>
+ * is null.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports an
+ * ExemptionMechanismSpi implementation for the
+ * specified algorithm.
+ *
+ * @see java.security.Provider
+ */
+ public static final ExemptionMechanism getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ Instance instance = JceSecurity.getInstance("ExemptionMechanism",
+ ExemptionMechanismSpi.class, algorithm);
+ return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+
+ /**
+ * Returns an <code>ExemptionMechanism</code> object that implements the
+ * specified exemption mechanism algorithm.
+ *
+ * <p> A new ExemptionMechanism object encapsulating the
+ * ExemptionMechanismSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+
+ * @param algorithm the standard name of the requested exemption mechanism.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard exemption mechanism names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new <code>ExemptionMechanism</code> object.
+ *
+ * @exception NullPointerException if <code>algorithm</code>
+ * is null.
+ *
+ * @exception NoSuchAlgorithmException if an ExemptionMechanismSpi
+ * implementation for the specified algorithm is not
+ * available from the specified provider.
+ *
+ * @exception NoSuchProviderException if the specified provider is not
+ * registered in the security provider list.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static final ExemptionMechanism getInstance(String algorithm,
+ String provider) throws NoSuchAlgorithmException,
+ NoSuchProviderException {
+ Instance instance = JceSecurity.getInstance("ExemptionMechanism",
+ ExemptionMechanismSpi.class, algorithm, provider);
+ return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns an <code>ExemptionMechanism</code> object that implements the
+ * specified exemption mechanism algorithm.
+ *
+ * <p> A new ExemptionMechanism object encapsulating the
+ * ExemptionMechanismSpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * @param algorithm the standard name of the requested exemption mechanism.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard exemption mechanism names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new <code>ExemptionMechanism</code> object.
+ *
+ * @exception NullPointerException if <code>algorithm</code>
+ * is null.
+ *
+ * @exception NoSuchAlgorithmException if an ExemptionMechanismSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null.
+ *
+ * @see java.security.Provider
+ */
+ public static final ExemptionMechanism getInstance(String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Instance instance = JceSecurity.getInstance("ExemptionMechanism",
+ ExemptionMechanismSpi.class, algorithm, provider);
+ return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns the provider of this <code>ExemptionMechanism</code> object.
+ *
+ * @return the provider of this <code>ExemptionMechanism</code> object.
+ */
+ public final Provider getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Returns whether the result blob has been generated successfully by this
+ * exemption mechanism.
+ *
+ * <p>The method also makes sure that the key passed in is the same as
+ * the one this exemption mechanism used in initializing and generating
+ * phases.
+ *
+ * @param key the key the crypto is going to use.
+ *
+ * @return whether the result blob of the same key has been generated
+ * successfully by this exemption mechanism; false if <code>key</code>
+ * is null.
+ *
+ * @exception ExemptionMechanismException if problem(s) encountered
+ * while determining whether the result blob has been generated successfully
+ * by this exemption mechanism object.
+ */
+ public final boolean isCryptoAllowed(Key key)
+ throws ExemptionMechanismException {
+ boolean ret = false;
+ if (done && (key != null)) {
+ // Check if the key passed in is the same as the one
+ // this exemption mechanism used.
+ ret = keyStored.equals(key);
+ }
+ return ret;
+ }
+
+ /**
+ * Returns the length in bytes that an output buffer would need to be in
+ * order to hold the result of the next
+ * {@link #genExemptionBlob(byte[]) genExemptionBlob}
+ * operation, given the input length <code>inputLen</code> (in bytes).
+ *
+ * <p>The actual output length of the next
+ * {@link #genExemptionBlob(byte[]) genExemptionBlob}
+ * call may be smaller than the length returned by this method.
+ *
+ * @param inputLen the input length (in bytes)
+ *
+ * @return the required output buffer size (in bytes)
+ *
+ * @exception IllegalStateException if this exemption mechanism is in a
+ * wrong state (e.g., has not yet been initialized)
+ */
+ public final int getOutputSize(int inputLen) throws IllegalStateException {
+ if (!initialized) {
+ throw new IllegalStateException(
+ "ExemptionMechanism not initialized");
+ }
+ if (inputLen < 0) {
+ throw new IllegalArgumentException(
+ "Input size must be equal to " + "or greater than zero");
+ }
+ return exmechSpi.engineGetOutputSize(inputLen);
+ }
+
+ /**
+ * Initializes this exemption mechanism with a key.
+ *
+ * <p>If this exemption mechanism requires any algorithm parameters
+ * that cannot be derived from the given <code>key</code>, the
+ * underlying exemption mechanism implementation is supposed to
+ * generate the required parameters itself (using provider-specific
+ * default values); in the case that algorithm parameters must be
+ * specified by the caller, an <code>InvalidKeyException</code> is raised.
+ *
+ * @param key the key for this exemption mechanism
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * this exemption mechanism.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of initializing.
+ */
+ public final void init(Key key)
+ throws InvalidKeyException, ExemptionMechanismException {
+ done = false;
+ initialized = false;
+
+ keyStored = key;
+ exmechSpi.engineInit(key);
+ initialized = true;
+ }
+
+ /**
+ * Initializes this exemption mechanism with a key and a set of algorithm
+ * parameters.
+ *
+ * <p>If this exemption mechanism requires any algorithm parameters
+ * and <code>params</code> is null, the underlying exemption
+ * mechanism implementation is supposed to generate the required
+ * parameters itself (using provider-specific default values); in the case
+ * that algorithm parameters must be specified by the caller, an
+ * <code>InvalidAlgorithmParameterException</code> is raised.
+ *
+ * @param key the key for this exemption mechanism
+ * @param params the algorithm parameters
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * this exemption mechanism.
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this exemption mechanism.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of initializing.
+ */
+ public final void init(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException,
+ ExemptionMechanismException {
+ done = false;
+ initialized = false;
+
+ keyStored = key;
+ exmechSpi.engineInit(key, params);
+ initialized = true;
+ }
+
+ /**
+ * Initializes this exemption mechanism with a key and a set of algorithm
+ * parameters.
+ *
+ * <p>If this exemption mechanism requires any algorithm parameters
+ * and <code>params</code> is null, the underlying exemption mechanism
+ * implementation is supposed to generate the required parameters itself
+ * (using provider-specific default values); in the case that algorithm
+ * parameters must be specified by the caller, an
+ * <code>InvalidAlgorithmParameterException</code> is raised.
+ *
+ * @param key the key for this exemption mechanism
+ * @param params the algorithm parameters
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * this exemption mechanism.
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this exemption mechanism.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of initializing.
+ */
+ public final void init(Key key, AlgorithmParameters params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException,
+ ExemptionMechanismException {
+ done = false;
+ initialized = false;
+
+ keyStored = key;
+ exmechSpi.engineInit(key, params);
+ initialized = true;
+ }
+
+ /**
+ * Generates the exemption mechanism key blob.
+ *
+ * @return the new buffer with the result key blob.
+ *
+ * @exception IllegalStateException if this exemption mechanism is in
+ * a wrong state (e.g., has not been initialized).
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of generating.
+ */
+ public final byte[] genExemptionBlob() throws IllegalStateException,
+ ExemptionMechanismException {
+ if (!initialized) {
+ throw new IllegalStateException(
+ "ExemptionMechanism not initialized");
+ }
+ byte[] blob = exmechSpi.engineGenExemptionBlob();
+ done = true;
+ return blob;
+ }
+
+ /**
+ * Generates the exemption mechanism key blob, and stores the result in
+ * the <code>output</code> buffer.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * @param output the buffer for the result
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this exemption mechanism is in
+ * a wrong state (e.g., has not been initialized).
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of generating.
+ */
+ public final int genExemptionBlob(byte[] output)
+ throws IllegalStateException, ShortBufferException,
+ ExemptionMechanismException {
+ if (!initialized) {
+ throw new IllegalStateException
+ ("ExemptionMechanism not initialized");
+ }
+ int n = exmechSpi.engineGenExemptionBlob(output, 0);
+ done = true;
+ return n;
+ }
+
+ /**
+ * Generates the exemption mechanism key blob, and stores the result in
+ * the <code>output</code> buffer, starting at <code>outputOffset</code>
+ * inclusive.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * {@link #getOutputSize(int) getOutputSize} to determine how big
+ * the output buffer should be.
+ *
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception IllegalStateException if this exemption mechanism is in
+ * a wrong state (e.g., has not been initialized).
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of generating.
+ */
+ public final int genExemptionBlob(byte[] output, int outputOffset)
+ throws IllegalStateException, ShortBufferException,
+ ExemptionMechanismException {
+ if (!initialized) {
+ throw new IllegalStateException
+ ("ExemptionMechanism not initialized");
+ }
+ int n = exmechSpi.engineGenExemptionBlob(output, outputOffset);
+ done = true;
+ return n;
+ }
+
+ /**
+ * Ensures that the key stored away by this ExemptionMechanism
+ * object will be wiped out when there are no more references to it.
+ */
+ protected void finalize() {
+ keyStored = null;
+ // Are there anything else we could do?
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanismException.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanismException.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanismException.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,59 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This is the generic ExemptionMechanism exception.
+ *
+ * @since 1.4
+ */
+
+public class ExemptionMechanismException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 1572699429277957109L;
+
+ /**
+ * Constructs a ExemptionMechanismException with no detailed message.
+ * (A detailed message is a String that describes this particular
+ * exception.)
+ */
+ public ExemptionMechanismException() {
+ super();
+ }
+
+ /**
+ * Constructs a ExemptionMechanismException with the specified
+ * detailed message. (A detailed message is a String that describes
+ * this particular exception.)
+ *
+ * @param msg the detailed message.
+ */
+ public ExemptionMechanismException(String msg) {
+ super(msg);
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanismSpi.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanismSpi.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/ExemptionMechanismSpi.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,170 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.Key;
+import java.security.AlgorithmParameters;
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>ExemptionMechanism</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular exemption mechanism.
+ *
+ * @author Sharon Liu
+ *
+ * @since 1.4
+ */
+
+public abstract class ExemptionMechanismSpi {
+
+ /**
+ * Returns the length in bytes that an output buffer would need to be in
+ * order to hold the result of the next
+ * {@link #engineGenExemptionBlob(byte[], int) engineGenExemptionBlob}
+ * operation, given the input length <code>inputLen</code> (in bytes).
+ *
+ * <p>The actual output length of the next
+ * {@link #engineGenExemptionBlob(byte[], int) engineGenExemptionBlob}
+ * call may be smaller than the length returned by this method.
+ *
+ * @param inputLen the input length (in bytes)
+ *
+ * @return the required output buffer size (in bytes)
+ */
+ protected abstract int engineGetOutputSize(int inputLen);
+
+ /**
+ * Initializes this exemption mechanism with a key.
+ *
+ * <p>If this exemption mechanism requires any algorithm parameters
+ * that cannot be derived from the given <code>key</code>, the underlying
+ * exemption mechanism implementation is supposed to generate the required
+ * parameters itself (using provider-specific default values); in the case
+ * that algorithm parameters must be specified by the caller, an
+ * <code>InvalidKeyException</code> is raised.
+ *
+ * @param key the key for this exemption mechanism
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * this exemption mechanism.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of initializing.
+ */
+ protected abstract void engineInit(Key key)
+ throws InvalidKeyException, ExemptionMechanismException;
+
+ /**
+ * Initializes this exemption mechanism with a key and a set of algorithm
+ * parameters.
+ *
+ * <p>If this exemption mechanism requires any algorithm parameters and
+ * <code>params</code> is null, the underlying exemption mechanism
+ * implementation is supposed to generate the required parameters
+ * itself (using provider-specific default values); in the case that
+ * algorithm parameters must be specified by the caller, an
+ * <code>InvalidAlgorithmParameterException</code> is raised.
+ *
+ * @param key the key for this exemption mechanism
+ * @param params the algorithm parameters
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * this exemption mechanism.
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this exemption mechanism.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of initializing.
+ */
+ protected abstract void engineInit(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException,
+ ExemptionMechanismException;
+
+ /**
+ * Initializes this exemption mechanism with a key and a set of algorithm
+ * parameters.
+ *
+ * <p>If this exemption mechanism requires any algorithm parameters
+ * and <code>params</code> is null, the underlying exemption mechanism
+ * implementation is supposed to generate the required parameters
+ * itself (using provider-specific default values); in the case that
+ * algorithm parameters must be specified by the caller, an
+ * <code>InvalidAlgorithmParameterException</code> is raised.
+ *
+ * @param key the key for this exemption mechanism
+ * @param params the algorithm parameters
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * this exemption mechanism.
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this exemption mechanism.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of initializing.
+ */
+ protected abstract void engineInit(Key key, AlgorithmParameters params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException,
+ ExemptionMechanismException;
+
+ /**
+ * Generates the exemption mechanism key blob.
+ *
+ * @return the new buffer with the result key blob.
+ *
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of generating.
+ */
+ protected abstract byte[] engineGenExemptionBlob()
+ throws ExemptionMechanismException;
+
+ /**
+ * Generates the exemption mechanism key blob, and stores the result in
+ * the <code>output</code> buffer, starting at <code>outputOffset</code>
+ * inclusive.
+ *
+ * <p>If the <code>output</code> buffer is too small to hold the result,
+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
+ * call with a larger output buffer. Use
+ * {@link #engineGetOutputSize(int) engineGetOutputSize} to determine
+ * how big the output buffer should be.
+ *
+ * @param output the buffer for the result
+ * @param outputOffset the offset in <code>output</code> where the result
+ * is stored
+ *
+ * @return the number of bytes stored in <code>output</code>
+ *
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result.
+ * @exception ExemptionMechanismException if problem(s) encountered in the
+ * process of generating.
+ */
+ protected abstract int engineGenExemptionBlob
+ (byte[] output, int outputOffset)
+ throws ShortBufferException, ExemptionMechanismException;
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/IllegalBlockSizeException.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/IllegalBlockSizeException.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/IllegalBlockSizeException.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,60 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+/**
+ * This exception is thrown when the length of data provided to a block
+ * cipher is incorrect, i.e., does not match the block size of the cipher.
+ *
+ * @author Jan Luehe
+ *
+ * @since 1.4
+ */
+
+public class IllegalBlockSizeException
+ extends java.security.GeneralSecurityException {
+
+ private static final long serialVersionUID = -1965144811953540392L;
+
+ /**
+ * Constructs an IllegalBlockSizeException with no detail message.
+ * A detail message is a String that describes this particular
+ * exception.
+ */
+ public IllegalBlockSizeException() {
+ super();
+ }
+
+ /**
+ * Constructs an IllegalBlockSizeException with the specified
+ * detail message.
+ *
+ * @param msg the detail message.
+ */
+ public IllegalBlockSizeException(String msg) {
+ super(msg);
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/JceSecurity.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/JceSecurity.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/JceSecurity.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,92 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.util.*;
+import java.security.*;
+
+import java.security.Provider.Service;
+
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class instantiates implementations of JCE engine classes from
+ * providers registered with the java.security.Security object.
+ *
+ * @author Jan Luehe
+ * @author Sharon Liu
+ * @since 1.4
+ */
+
+final class JceSecurity {
+
+ // Used in KeyGenerator, Cipher and KeyAgreement.
+ static final SecureRandom RANDOM = new SecureRandom();
+
+ /*
+ * Don't let anyone instantiate this.
+ */
+ private JceSecurity() {
+ }
+
+ static Instance getInstance(String type, Class clazz, String algorithm,
+ String provider) throws NoSuchAlgorithmException,
+ NoSuchProviderException {
+ Service s = GetInstance.getService(type, algorithm, provider);
+ return GetInstance.getInstance(s, clazz);
+ }
+
+ static Instance getInstance(String type, Class clazz, String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Service s = GetInstance.getService(type, algorithm, provider);
+ return GetInstance.getInstance(s, clazz);
+ }
+
+ static Instance getInstance(String type, Class clazz, String algorithm)
+ throws NoSuchAlgorithmException {
+ List services = GetInstance.getServices(type, algorithm);
+ NoSuchAlgorithmException failure = null;
+ for (Iterator t = services.iterator(); t.hasNext(); ) {
+ Service s = (Service)t.next();
+ try {
+ Instance instance = GetInstance.getInstance(s, clazz);
+ return instance;
+ } catch (NoSuchAlgorithmException e) {
+ failure = e;
+ }
+ }
+ throw new NoSuchAlgorithmException("Algorithm " + algorithm
+ + " not available", failure);
+ }
+
+ // Used to return whether this provider is properly signed and
+ // can be used by JCE. These days just returns true. Still used
+ // in SecretKeyFactory, KeyGenerator, Mac and KeyAgreement.
+ static boolean canUseProvider(Provider p) {
+ return true;
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/KeyAgreement.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/KeyAgreement.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/KeyAgreement.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,625 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.util.*;
+
+import java.security.*;
+import java.security.Provider.Service;
+import java.security.spec.*;
+
+import sun.security.util.Debug;
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class provides the functionality of a key agreement (or key
+ * exchange) protocol.
+ * <p>
+ * The keys involved in establishing a shared secret are created by one of the
+ * key generators (<code>KeyPairGenerator</code> or
+ * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
+ * an intermediate phase of the key agreement protocol.
+ *
+ * <p> For each of the correspondents in the key exchange, <code>doPhase</code>
+ * needs to be called. For example, if this key exchange is with one other
+ * party, <code>doPhase</code> needs to be called once, with the
+ * <code>lastPhase</code> flag set to <code>true</code>.
+ * If this key exchange is
+ * with two other parties, <code>doPhase</code> needs to be called twice,
+ * the first time setting the <code>lastPhase</code> flag to
+ * <code>false</code>, and the second time setting it to <code>true</code>.
+ * There may be any number of parties involved in a key exchange.
+ *
+ * @author Jan Luehe
+ *
+ * @see KeyGenerator
+ * @see SecretKey
+ * @since 1.4
+ */
+
+public class KeyAgreement {
+
+ private static final Debug debug =
+ Debug.getInstance("jca", "KeyAgreement");
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation (delegate)
+ private KeyAgreementSpi spi;
+
+ // The name of the key agreement algorithm.
+ private final String algorithm;
+
+ // next service to try in provider selection
+ // null once provider is selected
+ private Service firstService;
+
+ // remaining services to try in provider selection
+ // null once provider is selected
+ private Iterator serviceIterator;
+
+ private final Object lock;
+
+ /**
+ * Creates a KeyAgreement object.
+ *
+ * @param keyAgreeSpi the delegate
+ * @param provider the provider
+ * @param algorithm the algorithm
+ */
+ protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider,
+ String algorithm) {
+ this.spi = keyAgreeSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ lock = null;
+ }
+
+ private KeyAgreement(Service s, Iterator t, String algorithm) {
+ firstService = s;
+ serviceIterator = t;
+ this.algorithm = algorithm;
+ lock = new Object();
+ }
+
+ /**
+ * Returns the algorithm name of this <code>KeyAgreement</code> object.
+ *
+ * <p>This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this
+ * <code>KeyAgreement</code> object.
+ *
+ * @return the algorithm name of this <code>KeyAgreement</code> object.
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Returns a <code>KeyAgreement</code> object that implements the
+ * specified key agreement algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new KeyAgreement object encapsulating the
+ * KeyAgreementSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested key agreement
+ * algorithm.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new <code>KeyAgreement</code> object.
+ *
+ * @exception NullPointerException if the specified algorithm
+ * is null.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * KeyAgreementSpi implementation for the
+ * specified algorithm.
+ *
+ * @see java.security.Provider
+ */
+ public static final KeyAgreement getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ List services = GetInstance.getServices("KeyAgreement", algorithm);
+ // make sure there is at least one service from a signed provider
+ Iterator t = services.iterator();
+ while (t.hasNext()) {
+ Service s = (Service)t.next();
+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
+ continue;
+ }
+ return new KeyAgreement(s, t, algorithm);
+ }
+ throw new NoSuchAlgorithmException
+ ("Algorithm " + algorithm + " not available");
+ }
+
+ /**
+ * Returns a <code>KeyAgreement</code> object that implements the
+ * specified key agreement algorithm.
+ *
+ * <p> A new KeyAgreement object encapsulating the
+ * KeyAgreementSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested key agreement
+ * algorithm.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new <code>KeyAgreement</code> object.
+ *
+ * @exception NullPointerException if the specified algorithm
+ * is null.
+ *
+ * @exception NoSuchAlgorithmException if a KeyAgreementSpi
+ * implementation for the specified algorithm is not
+ * available from the specified provider.
+ *
+ * @exception NoSuchProviderException if the specified provider is not
+ * registered in the security provider list.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static final KeyAgreement getInstance(String algorithm,
+ String provider) throws NoSuchAlgorithmException,
+ NoSuchProviderException {
+ Instance instance = JceSecurity.getInstance
+ ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
+ return new KeyAgreement((KeyAgreementSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a <code>KeyAgreement</code> object that implements the
+ * specified key agreement algorithm.
+ *
+ * <p> A new KeyAgreement object encapsulating the
+ * KeyAgreementSpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * @param algorithm the standard name of the requested key agreement
+ * algorithm.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new <code>KeyAgreement</code> object.
+ *
+ * @exception NullPointerException if the specified algorithm
+ * is null.
+ *
+ * @exception NoSuchAlgorithmException if a KeyAgreementSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null.
+ *
+ * @see java.security.Provider
+ */
+ public static final KeyAgreement getInstance(String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Instance instance = JceSecurity.getInstance
+ ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
+ return new KeyAgreement((KeyAgreementSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ // max number of debug warnings to print from chooseFirstProvider()
+ private static int warnCount = 10;
+
+ /**
+ * Choose the Spi from the first provider available. Used if
+ * delayed provider selection is not possible because init()
+ * is not the first method called.
+ */
+ void chooseFirstProvider() {
+ if (spi != null) {
+ return;
+ }
+ synchronized (lock) {
+ if (spi != null) {
+ return;
+ }
+ if (debug != null) {
+ int w = --warnCount;
+ if (w >= 0) {
+ debug.println("KeyAgreement.init() not first method "
+ + "called, disabling delayed provider selection");
+ if (w == 0) {
+ debug.println("Further warnings of this type will "
+ + "be suppressed");
+ }
+ new Exception("Call trace").printStackTrace();
+ }
+ }
+ Exception lastException = null;
+ while ((firstService != null) || serviceIterator.hasNext()) {
+ Service s;
+ if (firstService != null) {
+ s = firstService;
+ firstService = null;
+ } else {
+ s = (Service)serviceIterator.next();
+ }
+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
+ continue;
+ }
+ try {
+ Object obj = s.newInstance(null);
+ if (obj instanceof KeyAgreementSpi == false) {
+ continue;
+ }
+ spi = (KeyAgreementSpi)obj;
+ provider = s.getProvider();
+ // not needed any more
+ firstService = null;
+ serviceIterator = null;
+ return;
+ } catch (Exception e) {
+ lastException = e;
+ }
+ }
+ ProviderException e = new ProviderException
+ ("Could not construct KeyAgreementSpi instance");
+ if (lastException != null) {
+ e.initCause(lastException);
+ }
+ throw e;
+ }
+ }
+
+ private final static int I_NO_PARAMS = 1;
+ private final static int I_PARAMS = 2;
+
+ private void implInit(KeyAgreementSpi spi, int type, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (type == I_NO_PARAMS) {
+ spi.engineInit(key, random);
+ } else { // I_PARAMS
+ spi.engineInit(key, params, random);
+ }
+ }
+
+ private void chooseProvider(int initType, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ synchronized (lock) {
+ if (spi != null) {
+ implInit(spi, initType, key, params, random);
+ return;
+ }
+ Exception lastException = null;
+ while ((firstService != null) || serviceIterator.hasNext()) {
+ Service s;
+ if (firstService != null) {
+ s = firstService;
+ firstService = null;
+ } else {
+ s = (Service)serviceIterator.next();
+ }
+ // if provider says it does not support this key, ignore it
+ if (s.supportsParameter(key) == false) {
+ continue;
+ }
+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
+ continue;
+ }
+ try {
+ KeyAgreementSpi spi = (KeyAgreementSpi)s.newInstance(null);
+ implInit(spi, initType, key, params, random);
+ provider = s.getProvider();
+ this.spi = spi;
+ firstService = null;
+ serviceIterator = null;
+ return;
+ } catch (Exception e) {
+ // NoSuchAlgorithmException from newInstance()
+ // InvalidKeyException from init()
+ // RuntimeException (ProviderException) from init()
+ if (lastException == null) {
+ lastException = e;
+ }
+ }
+ }
+ // no working provider found, fail
+ if (lastException instanceof InvalidKeyException) {
+ throw (InvalidKeyException)lastException;
+ }
+ if (lastException instanceof InvalidAlgorithmParameterException) {
+ throw (InvalidAlgorithmParameterException)lastException;
+ }
+ if (lastException instanceof RuntimeException) {
+ throw (RuntimeException)lastException;
+ }
+ String kName = (key != null) ? key.getClass().getName() : "(null)";
+ throw new InvalidKeyException
+ ("No installed provider supports this key: "
+ + kName, lastException);
+ }
+ }
+
+ /**
+ * Returns the provider of this <code>KeyAgreement</code> object.
+ *
+ * @return the provider of this <code>KeyAgreement</code> object
+ */
+ public final Provider getProvider() {
+ chooseFirstProvider();
+ return this.provider;
+ }
+
+ /**
+ * Initializes this key agreement with the given key, which is required to
+ * contain all the algorithm parameters required for this key agreement.
+ *
+ * <p> If this key agreement requires any random bytes, it will get
+ * them using the
+ * {@link SecureRandom <code>SecureRandom</code>}
+ * implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ *
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ */
+ public final void init(Key key) throws InvalidKeyException {
+ init(key, JceSecurity.RANDOM);
+ }
+
+ /**
+ * Initializes this key agreement with the given key and source of
+ * randomness. The given key is required to contain all the algorithm
+ * parameters required for this key agreement.
+ *
+ * <p> If the key agreement algorithm requires random bytes, it gets them
+ * from the given source of randomness, <code>random</code>.
+ * However, if the underlying
+ * algorithm implementation does not require any random bytes,
+ * <code>random</code> is ignored.
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ */
+ public final void init(Key key, SecureRandom random)
+ throws InvalidKeyException {
+ if (spi != null) {
+ spi.engineInit(key, random);
+ } else {
+ try {
+ chooseProvider(I_NO_PARAMS, key, null, random);
+ } catch (InvalidAlgorithmParameterException e) {
+ // should never occur
+ throw new InvalidKeyException(e);
+ }
+ }
+ }
+
+ /**
+ * Initializes this key agreement with the given key and set of
+ * algorithm parameters.
+ *
+ * <p> If this key agreement requires any random bytes, it will get
+ * them using the
+ * {@link SecureRandom <code>SecureRandom</code>}
+ * implementation of the highest-priority
+ * installed provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param params the key agreement parameters
+ *
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key agreement.
+ */
+ public final void init(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ init(key, params, JceSecurity.RANDOM);
+ }
+
+ /**
+ * Initializes this key agreement with the given key, set of
+ * algorithm parameters, and source of randomness.
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param params the key agreement parameters
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key agreement.
+ */
+ public final void init(Key key, AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ if (spi != null) {
+ spi.engineInit(key, params, random);
+ } else {
+ chooseProvider(I_PARAMS, key, params, random);
+ }
+ }
+
+ /**
+ * Executes the next phase of this key agreement with the given
+ * key that was received from one of the other parties involved in this key
+ * agreement.
+ *
+ * @param key the key for this phase. For example, in the case of
+ * Diffie-Hellman between 2 parties, this would be the other party's
+ * Diffie-Hellman public key.
+ * @param lastPhase flag which indicates whether or not this is the last
+ * phase of this key agreement.
+ *
+ * @return the (intermediate) key resulting from this phase, or null
+ * if this phase does not yield a key
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * this phase.
+ * @exception IllegalStateException if this key agreement has not been
+ * initialized.
+ */
+ public final Key doPhase(Key key, boolean lastPhase)
+ throws InvalidKeyException, IllegalStateException
+ {
+ chooseFirstProvider();
+ return spi.engineDoPhase(key, lastPhase);
+ }
+
+ /**
+ * Generates the shared secret and returns it in a new buffer.
+ *
+ * <p>This method resets this <code>KeyAgreement</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>init</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @return the new buffer with the shared secret
+ *
+ * @exception IllegalStateException if this key agreement has not been
+ * completed yet
+ */
+ public final byte[] generateSecret() throws IllegalStateException {
+ chooseFirstProvider();
+ return spi.engineGenerateSecret();
+ }
+
+ /**
+ * Generates the shared secret, and places it into the buffer
+ * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
+ *
+ * <p>If the <code>sharedSecret</code> buffer is too small to hold the
+ * result, a <code>ShortBufferException</code> is thrown.
+ * In this case, this call should be repeated with a larger output buffer.
+ *
+ * <p>This method resets this <code>KeyAgreement</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>init</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @param sharedSecret the buffer for the shared secret
+ * @param offset the offset in <code>sharedSecret</code> where the
+ * shared secret will be stored
+ *
+ * @return the number of bytes placed into <code>sharedSecret</code>
+ *
+ * @exception IllegalStateException if this key agreement has not been
+ * completed yet
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the secret
+ */
+ public final int generateSecret(byte[] sharedSecret, int offset)
+ throws IllegalStateException, ShortBufferException
+ {
+ chooseFirstProvider();
+ return spi.engineGenerateSecret(sharedSecret, offset);
+ }
+
+ /**
+ * Creates the shared secret and returns it as a <code>SecretKey</code>
+ * object of the specified algorithm.
+ *
+ * <p>This method resets this <code>KeyAgreement</code> object, so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>init</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @param algorithm the requested secret-key algorithm
+ *
+ * @return the shared secret key
+ *
+ * @exception IllegalStateException if this key agreement has not been
+ * completed yet
+ * @exception NoSuchAlgorithmException if the specified secret-key
+ * algorithm is not available
+ * @exception InvalidKeyException if the shared secret-key material cannot
+ * be used to generate a secret key of the specified algorithm (e.g.,
+ * the key material is too short)
+ */
+ public final SecretKey generateSecret(String algorithm)
+ throws IllegalStateException, NoSuchAlgorithmException,
+ InvalidKeyException
+ {
+ chooseFirstProvider();
+ return spi.engineGenerateSecret(algorithm);
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/KeyAgreementSpi.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/KeyAgreementSpi.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/KeyAgreementSpi.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,204 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.*;
+import java.security.spec.*;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>KeyAgreement</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular key agreement algorithm.
+ *
+ * <p> The keys involved in establishing a shared secret are created by one
+ * of the
+ * key generators (<code>KeyPairGenerator</code> or
+ * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
+ * an intermediate phase of the key agreement protocol
+ * ({@link #engineDoPhase(java.security.Key, boolean) engineDoPhase}).
+ *
+ * <p> For each of the correspondents in the key exchange,
+ * <code>engineDoPhase</code>
+ * needs to be called. For example, if the key exchange is with one other
+ * party, <code>engineDoPhase</code> needs to be called once, with the
+ * <code>lastPhase</code> flag set to <code>true</code>.
+ * If the key exchange is
+ * with two other parties, <code>engineDoPhase</code> needs to be called twice,
+ * the first time setting the <code>lastPhase</code> flag to
+ * <code>false</code>, and the second time setting it to <code>true</code>.
+ * There may be any number of parties involved in a key exchange.
+ *
+ * @author Jan Luehe
+ *
+ * @see KeyGenerator
+ * @see SecretKey
+ * @since 1.4
+ */
+
+public abstract class KeyAgreementSpi {
+
+ /**
+ * Initializes this key agreement with the given key and source of
+ * randomness. The given key is required to contain all the algorithm
+ * parameters required for this key agreement.
+ *
+ * <p> If the key agreement algorithm requires random bytes, it gets them
+ * from the given source of randomness, <code>random</code>.
+ * However, if the underlying
+ * algorithm implementation does not require any random bytes,
+ * <code>random</code> is ignored.
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ */
+ protected abstract void engineInit(Key key, SecureRandom random)
+ throws InvalidKeyException;
+
+ /**
+ * Initializes this key agreement with the given key, set of
+ * algorithm parameters, and source of randomness.
+ *
+ * @param key the party's private information. For example, in the case
+ * of the Diffie-Hellman key agreement, this would be the party's own
+ * Diffie-Hellman private key.
+ * @param params the key agreement parameters
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the given key is
+ * inappropriate for this key agreement, e.g., is of the wrong type or
+ * has an incompatible algorithm type.
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key agreement.
+ */
+ protected abstract void engineInit(Key key, AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException;
+
+ /**
+ * Executes the next phase of this key agreement with the given
+ * key that was received from one of the other parties involved in this key
+ * agreement.
+ *
+ * @param key the key for this phase. For example, in the case of
+ * Diffie-Hellman between 2 parties, this would be the other party's
+ * Diffie-Hellman public key.
+ * @param lastPhase flag which indicates whether or not this is the last
+ * phase of this key agreement.
+ *
+ * @return the (intermediate) key resulting from this phase, or null if
+ * this phase does not yield a key
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * this phase.
+ * @exception IllegalStateException if this key agreement has not been
+ * initialized.
+ */
+ protected abstract Key engineDoPhase(Key key, boolean lastPhase)
+ throws InvalidKeyException, IllegalStateException;
+
+ /**
+ * Generates the shared secret and returns it in a new buffer.
+ *
+ * <p>This method resets this <code>KeyAgreementSpi</code> object,
+ * so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>engineInit</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @return the new buffer with the shared secret
+ *
+ * @exception IllegalStateException if this key agreement has not been
+ * completed yet
+ */
+ protected abstract byte[] engineGenerateSecret()
+ throws IllegalStateException;
+
+ /**
+ * Generates the shared secret, and places it into the buffer
+ * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
+ *
+ * <p>If the <code>sharedSecret</code> buffer is too small to hold the
+ * result, a <code>ShortBufferException</code> is thrown.
+ * In this case, this call should be repeated with a larger output buffer.
+ *
+ * <p>This method resets this <code>KeyAgreementSpi</code> object,
+ * so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>engineInit</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @param sharedSecret the buffer for the shared secret
+ * @param offset the offset in <code>sharedSecret</code> where the
+ * shared secret will be stored
+ *
+ * @return the number of bytes placed into <code>sharedSecret</code>
+ *
+ * @exception IllegalStateException if this key agreement has not been
+ * completed yet
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the secret
+ */
+ protected abstract int engineGenerateSecret(byte[] sharedSecret,
+ int offset)
+ throws IllegalStateException, ShortBufferException;
+
+ /**
+ * Creates the shared secret and returns it as a secret key object
+ * of the requested algorithm type.
+ *
+ * <p>This method resets this <code>KeyAgreementSpi</code> object,
+ * so that it
+ * can be reused for further key agreements. Unless this key agreement is
+ * reinitialized with one of the <code>engineInit</code> methods, the same
+ * private information and algorithm parameters will be used for
+ * subsequent key agreements.
+ *
+ * @param algorithm the requested secret key algorithm
+ *
+ * @return the shared secret key
+ *
+ * @exception IllegalStateException if this key agreement has not been
+ * completed yet
+ * @exception NoSuchAlgorithmException if the requested secret key
+ * algorithm is not available
+ * @exception InvalidKeyException if the shared secret key material cannot
+ * be used to generate a secret key of the requested algorithm type (e.g.,
+ * the key material is too short)
+ */
+ protected abstract SecretKey engineGenerateSecret(String algorithm)
+ throws IllegalStateException, NoSuchAlgorithmException,
+ InvalidKeyException;
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/KeyGenerator.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/KeyGenerator.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/KeyGenerator.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,526 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.util.*;
+
+import java.security.*;
+import java.security.Provider.Service;
+import java.security.spec.*;
+
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class provides the functionality of a secret (symmetric) key generator.
+ *
+ * <p>Key generators are constructed using one of the <code>getInstance</code>
+ * class methods of this class.
+ *
+ * <p>KeyGenerator objects are reusable, i.e., after a key has been
+ * generated, the same KeyGenerator object can be re-used to generate further
+ * keys.
+ *
+ * <p>There are two ways to generate a key: in an algorithm-independent
+ * manner, and in an algorithm-specific manner.
+ * The only difference between the two is the initialization of the object:
+ *
+ * <ul>
+ * <li><b>Algorithm-Independent Initialization</b>
+ * <p>All key generators share the concepts of a <i>keysize</i> and a
+ * <i>source of randomness</i>.
+ * There is an
+ * {@link #init(int, java.security.SecureRandom) init}
+ * method in this KeyGenerator class that takes these two universally
+ * shared types of arguments. There is also one that takes just a
+ * <code>keysize</code> argument, and uses the SecureRandom implementation
+ * of the highest-priority installed provider as the source of randomness
+ * (or a system-provided source of randomness if none of the installed
+ * providers supply a SecureRandom implementation), and one that takes just a
+ * source of randomness.
+ *
+ * <p>Since no other parameters are specified when you call the above
+ * algorithm-independent <code>init</code> methods, it is up to the
+ * provider what to do about the algorithm-specific parameters (if any) to be
+ * associated with each of the keys.
+ * <p>
+ *
+ * <li><b>Algorithm-Specific Initialization</b>
+ * <p>For situations where a set of algorithm-specific parameters already
+ * exists, there are two
+ * {@link #init(java.security.spec.AlgorithmParameterSpec) init}
+ * methods that have an <code>AlgorithmParameterSpec</code>
+ * argument. One also has a <code>SecureRandom</code> argument, while the
+ * other uses the SecureRandom implementation
+ * of the highest-priority installed provider as the source of randomness
+ * (or a system-provided source of randomness if none of the installed
+ * providers supply a SecureRandom implementation).
+ * </ul>
+ *
+ * <p>In case the client does not explicitly initialize the KeyGenerator
+ * (via a call to an <code>init</code> method), each provider must
+ * supply (and document) a default initialization.
+ *
+ * @author Jan Luehe
+ *
+ * @see SecretKey
+ * @since 1.4
+ */
+
+public class KeyGenerator {
+
+ // see java.security.KeyPairGenerator for failover notes
+
+ private final static int I_NONE = 1;
+ private final static int I_RANDOM = 2;
+ private final static int I_PARAMS = 3;
+ private final static int I_SIZE = 4;
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation (delegate)
+ private volatile KeyGeneratorSpi spi;
+
+ // The algorithm
+ private final String algorithm;
+
+ private final Object lock = new Object();
+
+ private Iterator serviceIterator;
+
+ private int initType;
+ private int initKeySize;
+ private AlgorithmParameterSpec initParams;
+ private SecureRandom initRandom;
+
+ /**
+ * Creates a KeyGenerator object.
+ *
+ * @param keyGenSpi the delegate
+ * @param provider the provider
+ * @param algorithm the algorithm
+ */
+ protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider,
+ String algorithm) {
+ this.spi = keyGenSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
+ this.algorithm = algorithm;
+ List list = GetInstance.getServices("KeyGenerator", algorithm);
+ serviceIterator = list.iterator();
+ initType = I_NONE;
+ // fetch and instantiate initial spi
+ if (nextSpi(null, false) == null) {
+ throw new NoSuchAlgorithmException
+ (algorithm + " KeyGenerator not available");
+ }
+ }
+
+ /**
+ * Returns the algorithm name of this <code>KeyGenerator</code> object.
+ *
+ * <p>This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this
+ * <code>KeyGenerator</code> object.
+ *
+ * @return the algorithm name of this <code>KeyGenerator</code> object.
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Returns a <code>KeyGenerator</code> object that generates secret keys
+ * for the specified algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new KeyGenerator object encapsulating the
+ * KeyGeneratorSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested key algorithm.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new <code>KeyGenerator</code> object.
+ *
+ * @exception NullPointerException if the specified algorithm is null.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * KeyGeneratorSpi implementation for the
+ * specified algorithm.
+ *
+ * @see java.security.Provider
+ */
+ public static final KeyGenerator getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ return new KeyGenerator(algorithm);
+ }
+
+ /**
+ * Returns a <code>KeyGenerator</code> object that generates secret keys
+ * for the specified algorithm.
+ *
+ * <p> A new KeyGenerator object encapsulating the
+ * KeyGeneratorSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested key algorithm.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new <code>KeyGenerator</code> object.
+ *
+ * @exception NullPointerException if the specified algorithm is null.
+ *
+ * @exception NoSuchAlgorithmException if a KeyGeneratorSpi
+ * implementation for the specified algorithm is not
+ * available from the specified provider.
+ *
+ * @exception NoSuchProviderException if the specified provider is not
+ * registered in the security provider list.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static final KeyGenerator getInstance(String algorithm,
+ String provider) throws NoSuchAlgorithmException,
+ NoSuchProviderException {
+ Instance instance = JceSecurity.getInstance("KeyGenerator",
+ KeyGeneratorSpi.class, algorithm, provider);
+ return new KeyGenerator((KeyGeneratorSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a <code>KeyGenerator</code> object that generates secret keys
+ * for the specified algorithm.
+ *
+ * <p> A new KeyGenerator object encapsulating the
+ * KeyGeneratorSpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * @param algorithm the standard name of the requested key algorithm.
+ * See Appendix A in the
+ * <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new <code>KeyGenerator</code> object.
+ *
+ * @exception NullPointerException if the specified algorithm is null.
+ *
+ * @exception NoSuchAlgorithmException if a KeyGeneratorSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null.
+ *
+ * @see java.security.Provider
+ */
+ public static final KeyGenerator getInstance(String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Instance instance = JceSecurity.getInstance("KeyGenerator",
+ KeyGeneratorSpi.class, algorithm, provider);
+ return new KeyGenerator((KeyGeneratorSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns the provider of this <code>KeyGenerator</code> object.
+ *
+ * @return the provider of this <code>KeyGenerator</code> object
+ */
+ public final Provider getProvider() {
+ synchronized (lock) {
+ disableFailover();
+ return provider;
+ }
+ }
+
+ /**
+ * Update the active spi of this class and return the next
+ * implementation for failover. If no more implemenations are
+ * available, this method returns null. However, the active spi of
+ * this class is never set to null.
+ */
+ private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi,
+ boolean reinit) {
+ synchronized (lock) {
+ // somebody else did a failover concurrently
+ // try that spi now
+ if ((oldSpi != null) && (oldSpi != spi)) {
+ return spi;
+ }
+ if (serviceIterator == null) {
+ return null;
+ }
+ while (serviceIterator.hasNext()) {
+ Service s = (Service)serviceIterator.next();
+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
+ continue;
+ }
+ try {
+ Object inst = s.newInstance(null);
+ // ignore non-spis
+ if (inst instanceof KeyGeneratorSpi == false) {
+ continue;
+ }
+ KeyGeneratorSpi spi = (KeyGeneratorSpi)inst;
+ if (reinit) {
+ if (initType == I_SIZE) {
+ spi.engineInit(initKeySize, initRandom);
+ } else if (initType == I_PARAMS) {
+ spi.engineInit(initParams, initRandom);
+ } else if (initType == I_RANDOM) {
+ spi.engineInit(initRandom);
+ } else if (initType != I_NONE) {
+ throw new AssertionError
+ ("KeyGenerator initType: " + initType);
+ }
+ }
+ provider = s.getProvider();
+ this.spi = spi;
+ return spi;
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ disableFailover();
+ return null;
+ }
+ }
+
+ void disableFailover() {
+ serviceIterator = null;
+ initType = 0;
+ initParams = null;
+ initRandom = null;
+ }
+
+ /**
+ * Initializes this key generator.
+ *
+ * @param random the source of randomness for this generator
+ */
+ public final void init(SecureRandom random) {
+ if (serviceIterator == null) {
+ spi.engineInit(random);
+ return;
+ }
+ RuntimeException failure = null;
+ KeyGeneratorSpi mySpi = spi;
+ do {
+ try {
+ mySpi.engineInit(random);
+ initType = I_RANDOM;
+ initKeySize = 0;
+ initParams = null;
+ initRandom = random;
+ return;
+ } catch (RuntimeException e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi, false);
+ }
+ } while (mySpi != null);
+ throw failure;
+ }
+
+ /**
+ * Initializes this key generator with the specified parameter set.
+ *
+ * <p> If this key generator requires any random bytes, it will get them
+ * using the
+ * {@link SecureRandom <code>SecureRandom</code>}
+ * implementation of the highest-priority installed
+ * provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ *
+ * @param params the key generation parameters
+ *
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key generator
+ */
+ public final void init(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ init(params, JceSecurity.RANDOM);
+ }
+
+ /**
+ * Initializes this key generator with the specified parameter
+ * set and a user-provided source of randomness.
+ *
+ * @param params the key generation parameters
+ * @param random the source of randomness for this key generator
+ *
+ * @exception InvalidAlgorithmParameterException if <code>params</code> is
+ * inappropriate for this key generator
+ */
+ public final void init(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ if (serviceIterator == null) {
+ spi.engineInit(params, random);
+ return;
+ }
+ Exception failure = null;
+ KeyGeneratorSpi mySpi = spi;
+ do {
+ try {
+ mySpi.engineInit(params, random);
+ initType = I_PARAMS;
+ initKeySize = 0;
+ initParams = params;
+ initRandom = random;
+ return;
+ } catch (Exception e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi, false);
+ }
+ } while (mySpi != null);
+ if (failure instanceof InvalidAlgorithmParameterException) {
+ throw (InvalidAlgorithmParameterException)failure;
+ }
+ if (failure instanceof RuntimeException) {
+ throw (RuntimeException)failure;
+ }
+ throw new InvalidAlgorithmParameterException("init() failed", failure);
+ }
+
+ /**
+ * Initializes this key generator for a certain keysize.
+ *
+ * <p> If this key generator requires any random bytes, it will get them
+ * using the
+ * {@link SecureRandom <code>SecureRandom</code>}
+ * implementation of the highest-priority installed
+ * provider as the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * SecureRandom, a system-provided source of randomness will be used.)
+ *
+ * @param keysize the keysize. This is an algorithm-specific metric,
+ * specified in number of bits.
+ *
+ * @exception InvalidParameterException if the keysize is wrong or not
+ * supported.
+ */
+ public final void init(int keysize) {
+ init(keysize, JceSecurity.RANDOM);
+ }
+
+ /**
+ * Initializes this key generator for a certain keysize, using a
+ * user-provided source of randomness.
+ *
+ * @param keysize the keysize. This is an algorithm-specific metric,
+ * specified in number of bits.
+ * @param random the source of randomness for this key generator
+ *
+ * @exception InvalidParameterException if the keysize is wrong or not
+ * supported.
+ */
+ public final void init(int keysize, SecureRandom random) {
+ if (serviceIterator == null) {
+ spi.engineInit(keysize, random);
+ return;
+ }
+ RuntimeException failure = null;
+ KeyGeneratorSpi mySpi = spi;
+ do {
+ try {
+ mySpi.engineInit(keysize, random);
+ initType = I_SIZE;
+ initKeySize = keysize;
+ initParams = null;
+ initRandom = random;
+ return;
+ } catch (RuntimeException e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi, false);
+ }
+ } while (mySpi != null);
+ throw failure;
+ }
+
+ /**
+ * Generates a secret key.
+ *
+ * @return the new key
+ */
+ public final SecretKey generateKey() {
+ if (serviceIterator == null) {
+ return spi.engineGenerateKey();
+ }
+ RuntimeException failure = null;
+ KeyGeneratorSpi mySpi = spi;
+ do {
+ try {
+ return mySpi.engineGenerateKey();
+ } catch (RuntimeException e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi, true);
+ }
+ } while (mySpi != null);
+ throw failure;
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/KeyGeneratorSpi.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/KeyGeneratorSpi.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/KeyGeneratorSpi.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,86 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.*;
+import java.security.spec.*;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>KeyGenerator</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a key generator for a particular algorithm.
+ *
+ * @author Jan Luehe
+ *
+ * @see SecretKey
+ * @since 1.4
+ */
+
+public abstract class KeyGeneratorSpi {
+
+ /**
+ * Initializes the key generator.
+ *
+ * @param random the source of randomness for this generator
+ */
+ protected abstract void engineInit(SecureRandom random);
+
+ /**
+ * Initializes the key generator with the specified parameter
+ * set and a user-provided source of randomness.
+ *
+ * @param params the key generation parameters
+ * @param random the source of randomness for this key generator
+ *
+ * @exception InvalidAlgorithmParameterException if <code>params</code> is
+ * inappropriate for this key generator
+ */
+ protected abstract void engineInit(AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException;
+
+ /**
+ * Initializes this key generator for a certain keysize, using the given
+ * source of randomness.
+ *
+ * @param keysize the keysize. This is an algorithm-specific metric,
+ * specified in number of bits.
+ * @param random the source of randomness for this key generator
+ *
+ * @exception InvalidParameterException if the keysize is wrong or not
+ * supported.
+ */
+ protected abstract void engineInit(int keysize, SecureRandom random);
+
+ /**
+ * Generates a secret key.
+ *
+ * @return the new key
+ */
+ protected abstract SecretKey engineGenerateKey();
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/Mac.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/Mac.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/Mac.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,643 @@
+/*
+ * Copyright 1998-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.util.*;
+
+import java.security.*;
+import java.security.Provider.Service;
+import java.security.spec.AlgorithmParameterSpec;
+
+import java.nio.ByteBuffer;
+
+import sun.security.util.Debug;
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class provides the functionality of a "Message Authentication Code"
+ * (MAC) algorithm.
+ *
+ * <p> A MAC provides a way to check
+ * the integrity of information transmitted over or stored in an unreliable
+ * medium, based on a secret key. Typically, message
+ * authentication codes are used between two parties that share a secret
+ * key in order to validate information transmitted between these
+ * parties.
+ *
+ * <p> A MAC mechanism that is based on cryptographic hash functions is
+ * referred to as HMAC. HMAC can be used with any cryptographic hash function,
+ * e.g., MD5 or SHA-1, in combination with a secret shared key. HMAC is
+ * specified in RFC 2104.
+ *
+ * @author Jan Luehe
+ *
+ * @since 1.4
+ */
+
+public class Mac implements Cloneable {
+
+ private static final Debug debug =
+ Debug.getInstance("jca", "Mac");
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation (delegate)
+ private MacSpi spi;
+
+ // The name of the MAC algorithm.
+ private final String algorithm;
+
+ // Has this object been initialized?
+ private boolean initialized = false;
+
+ // next service to try in provider selection
+ // null once provider is selected
+ private Service firstService;
+
+ // remaining services to try in provider selection
+ // null once provider is selected
+ private Iterator serviceIterator;
+
+ private final Object lock;
+
+ /**
+ * Creates a MAC object.
+ *
+ * @param macSpi the delegate
+ * @param provider the provider
+ * @param algorithm the algorithm
+ */
+ protected Mac(MacSpi macSpi, Provider provider, String algorithm) {
+ this.spi = macSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ serviceIterator = null;
+ lock = null;
+ }
+
+ private Mac(Service s, Iterator t, String algorithm) {
+ firstService = s;
+ serviceIterator = t;
+ this.algorithm = algorithm;
+ lock = new Object();
+ }
+
+ /**
+ * Returns the algorithm name of this <code>Mac</code> object.
+ *
+ * <p>This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this
+ * <code>Mac</code> object.
+ *
+ * @return the algorithm name of this <code>Mac</code> object.
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Returns a <code>Mac</code> object that implements the
+ * specified MAC algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new Mac object encapsulating the
+ * MacSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested MAC algorithm.
+ * See Appendix A in the <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new <code>Mac</code> object.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * MacSpi implementation for the
+ * specified algorithm.
+ *
+ * @see java.security.Provider
+ */
+ public static final Mac getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ List services = GetInstance.getServices("Mac", algorithm);
+ // make sure there is at least one service from a signed provider
+ Iterator t = services.iterator();
+ while (t.hasNext()) {
+ Service s = (Service)t.next();
+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
+ continue;
+ }
+ return new Mac(s, t, algorithm);
+ }
+ throw new NoSuchAlgorithmException
+ ("Algorithm " + algorithm + " not available");
+ }
+
+ /**
+ * Returns a <code>Mac</code> object that implements the
+ * specified MAC algorithm.
+ *
+ * <p> A new Mac object encapsulating the
+ * MacSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested MAC algorithm.
+ * See Appendix A in the <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new <code>Mac</code> object.
+ *
+ * @exception NoSuchAlgorithmException if a MacSpi
+ * implementation for the specified algorithm is not
+ * available from the specified provider.
+ *
+ * @exception NoSuchProviderException if the specified provider is not
+ * registered in the security provider list.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static final Mac getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ Instance instance = JceSecurity.getInstance
+ ("Mac", MacSpi.class, algorithm, provider);
+ return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a <code>Mac</code> object that implements the
+ * specified MAC algorithm.
+ *
+ * <p> A new Mac object encapsulating the
+ * MacSpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * @param algorithm the standard name of the requested MAC algorithm.
+ * See Appendix A in the <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new <code>Mac</code> object.
+ *
+ * @exception NoSuchAlgorithmException if a MacSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null.
+ *
+ * @see java.security.Provider
+ */
+ public static final Mac getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException {
+ Instance instance = JceSecurity.getInstance
+ ("Mac", MacSpi.class, algorithm, provider);
+ return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
+ }
+
+ // max number of debug warnings to print from chooseFirstProvider()
+ private static int warnCount = 10;
+
+ /**
+ * Choose the Spi from the first provider available. Used if
+ * delayed provider selection is not possible because init()
+ * is not the first method called.
+ */
+ void chooseFirstProvider() {
+ if ((spi != null) || (serviceIterator == null)) {
+ return;
+ }
+ synchronized (lock) {
+ if (spi != null) {
+ return;
+ }
+ if (debug != null) {
+ int w = --warnCount;
+ if (w >= 0) {
+ debug.println("Mac.init() not first method "
+ + "called, disabling delayed provider selection");
+ if (w == 0) {
+ debug.println("Further warnings of this type will "
+ + "be suppressed");
+ }
+ new Exception("Call trace").printStackTrace();
+ }
+ }
+ Exception lastException = null;
+ while ((firstService != null) || serviceIterator.hasNext()) {
+ Service s;
+ if (firstService != null) {
+ s = firstService;
+ firstService = null;
+ } else {
+ s = (Service)serviceIterator.next();
+ }
+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
+ continue;
+ }
+ try {
+ Object obj = s.newInstance(null);
+ if (obj instanceof MacSpi == false) {
+ continue;
+ }
+ spi = (MacSpi)obj;
+ provider = s.getProvider();
+ // not needed any more
+ firstService = null;
+ serviceIterator = null;
+ return;
+ } catch (NoSuchAlgorithmException e) {
+ lastException = e;
+ }
+ }
+ ProviderException e = new ProviderException
+ ("Could not construct MacSpi instance");
+ if (lastException != null) {
+ e.initCause(lastException);
+ }
+ throw e;
+ }
+ }
+
+ private void chooseProvider(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ synchronized (lock) {
+ if (spi != null) {
+ spi.engineInit(key, params);
+ return;
+ }
+ Exception lastException = null;
+ while ((firstService != null) || serviceIterator.hasNext()) {
+ Service s;
+ if (firstService != null) {
+ s = firstService;
+ firstService = null;
+ } else {
+ s = (Service)serviceIterator.next();
+ }
+ // if provider says it does not support this key, ignore it
+ if (s.supportsParameter(key) == false) {
+ continue;
+ }
+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
+ continue;
+ }
+ try {
+ MacSpi spi = (MacSpi)s.newInstance(null);
+ spi.engineInit(key, params);
+ provider = s.getProvider();
+ this.spi = spi;
+ firstService = null;
+ serviceIterator = null;
+ return;
+ } catch (Exception e) {
+ // NoSuchAlgorithmException from newInstance()
+ // InvalidKeyException from init()
+ // RuntimeException (ProviderException) from init()
+ if (lastException == null) {
+ lastException = e;
+ }
+ }
+ }
+ // no working provider found, fail
+ if (lastException instanceof InvalidKeyException) {
+ throw (InvalidKeyException)lastException;
+ }
+ if (lastException instanceof InvalidAlgorithmParameterException) {
+ throw (InvalidAlgorithmParameterException)lastException;
+ }
+ if (lastException instanceof RuntimeException) {
+ throw (RuntimeException)lastException;
+ }
+ String kName = (key != null) ? key.getClass().getName() : "(null)";
+ throw new InvalidKeyException
+ ("No installed provider supports this key: "
+ + kName, lastException);
+ }
+ }
+
+ /**
+ * Returns the provider of this <code>Mac</code> object.
+ *
+ * @return the provider of this <code>Mac</code> object.
+ */
+ public final Provider getProvider() {
+ chooseFirstProvider();
+ return this.provider;
+ }
+
+ /**
+ * Returns the length of the MAC in bytes.
+ *
+ * @return the MAC length in bytes.
+ */
+ public final int getMacLength() {
+ chooseFirstProvider();
+ return spi.engineGetMacLength();
+ }
+
+ /**
+ * Initializes this <code>Mac</code> object with the given key.
+ *
+ * @param key the key.
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this MAC.
+ */
+ public final void init(Key key) throws InvalidKeyException {
+ try {
+ if (spi != null) {
+ spi.engineInit(key, null);
+ } else {
+ chooseProvider(key, null);
+ }
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new InvalidKeyException("init() failed", e);
+ }
+ initialized = true;
+ }
+
+ /**
+ * Initializes this <code>Mac</code> object with the given key and
+ * algorithm parameters.
+ *
+ * @param key the key.
+ * @param params the algorithm parameters.
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this MAC.
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this MAC.
+ */
+ public final void init(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (spi != null) {
+ spi.engineInit(key, params);
+ } else {
+ chooseProvider(key, params);
+ }
+ initialized = true;
+ }
+
+ /**
+ * Processes the given byte.
+ *
+ * @param input the input byte to be processed.
+ *
+ * @exception IllegalStateException if this <code>Mac</code> has not been
+ * initialized.
+ */
+ public final void update(byte input) throws IllegalStateException {
+ chooseFirstProvider();
+ if (initialized == false) {
+ throw new IllegalStateException("MAC not initialized");
+ }
+ spi.engineUpdate(input);
+ }
+
+ /**
+ * Processes the given array of bytes.
+ *
+ * @param input the array of bytes to be processed.
+ *
+ * @exception IllegalStateException if this <code>Mac</code> has not been
+ * initialized.
+ */
+ public final void update(byte[] input) throws IllegalStateException {
+ chooseFirstProvider();
+ if (initialized == false) {
+ throw new IllegalStateException("MAC not initialized");
+ }
+ if (input != null) {
+ spi.engineUpdate(input, 0, input.length);
+ }
+ }
+
+ /**
+ * Processes the first <code>len</code> bytes in <code>input</code>,
+ * starting at <code>offset</code> inclusive.
+ *
+ * @param input the input buffer.
+ * @param offset the offset in <code>input</code> where the input starts.
+ * @param len the number of bytes to process.
+ *
+ * @exception IllegalStateException if this <code>Mac</code> has not been
+ * initialized.
+ */
+ public final void update(byte[] input, int offset, int len)
+ throws IllegalStateException {
+ chooseFirstProvider();
+ if (initialized == false) {
+ throw new IllegalStateException("MAC not initialized");
+ }
+
+ if (input != null) {
+ if ((offset < 0) || (len > (input.length - offset)) || (len < 0))
+ throw new IllegalArgumentException("Bad arguments");
+ spi.engineUpdate(input, offset, len);
+ }
+ }
+
+ /**
+ * Processes <code>input.remaining()</code> bytes in the ByteBuffer
+ * <code>input</code>, starting at <code>input.position()</code>.
+ * Upon return, the buffer's position will be equal to its limit;
+ * its limit will not have changed.
+ *
+ * @param input the ByteBuffer
+ *
+ * @exception IllegalStateException if this <code>Mac</code> has not been
+ * initialized.
+ * @since 1.5
+ */
+ public final void update(ByteBuffer input) {
+ chooseFirstProvider();
+ if (initialized == false) {
+ throw new IllegalStateException("MAC not initialized");
+ }
+ if (input == null) {
+ throw new IllegalArgumentException("Buffer must not be null");
+ }
+ spi.engineUpdate(input);
+ }
+
+ /**
+ * Finishes the MAC operation.
+ *
+ * <p>A call to this method resets this <code>Mac</code> object to the
+ * state it was in when previously initialized via a call to
+ * <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ * That is, the object is reset and available to generate another MAC from
+ * the same key, if desired, via new calls to <code>update</code> and
+ * <code>doFinal</code>.
+ * (In order to reuse this <code>Mac</code> object with a different key,
+ * it must be reinitialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ *
+ * @return the MAC result.
+ *
+ * @exception IllegalStateException if this <code>Mac</code> has not been
+ * initialized.
+ */
+ public final byte[] doFinal() throws IllegalStateException {
+ chooseFirstProvider();
+ if (initialized == false) {
+ throw new IllegalStateException("MAC not initialized");
+ }
+ byte[] mac = spi.engineDoFinal();
+ spi.engineReset();
+ return mac;
+ }
+
+ /**
+ * Finishes the MAC operation.
+ *
+ * <p>A call to this method resets this <code>Mac</code> object to the
+ * state it was in when previously initialized via a call to
+ * <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ * That is, the object is reset and available to generate another MAC from
+ * the same key, if desired, via new calls to <code>update</code> and
+ * <code>doFinal</code>.
+ * (In order to reuse this <code>Mac</code> object with a different key,
+ * it must be reinitialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ *
+ * <p>The MAC result is stored in <code>output</code>, starting at
+ * <code>outOffset</code> inclusive.
+ *
+ * @param output the buffer where the MAC result is stored
+ * @param outOffset the offset in <code>output</code> where the MAC is
+ * stored
+ *
+ * @exception ShortBufferException if the given output buffer is too small
+ * to hold the result
+ * @exception IllegalStateException if this <code>Mac</code> has not been
+ * initialized.
+ */
+ public final void doFinal(byte[] output, int outOffset)
+ throws ShortBufferException, IllegalStateException
+ {
+ chooseFirstProvider();
+ if (initialized == false) {
+ throw new IllegalStateException("MAC not initialized");
+ }
+ int macLen = getMacLength();
+ if (output == null || output.length-outOffset < macLen) {
+ throw new ShortBufferException
+ ("Cannot store MAC in output buffer");
+ }
+ byte[] mac = doFinal();
+ System.arraycopy(mac, 0, output, outOffset, macLen);
+ return;
+ }
+
+ /**
+ * Processes the given array of bytes and finishes the MAC operation.
+ *
+ * <p>A call to this method resets this <code>Mac</code> object to the
+ * state it was in when previously initialized via a call to
+ * <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ * That is, the object is reset and available to generate another MAC from
+ * the same key, if desired, via new calls to <code>update</code> and
+ * <code>doFinal</code>.
+ * (In order to reuse this <code>Mac</code> object with a different key,
+ * it must be reinitialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ *
+ * @param input data in bytes
+ * @return the MAC result.
+ *
+ * @exception IllegalStateException if this <code>Mac</code> has not been
+ * initialized.
+ */
+ public final byte[] doFinal(byte[] input) throws IllegalStateException
+ {
+ chooseFirstProvider();
+ if (initialized == false) {
+ throw new IllegalStateException("MAC not initialized");
+ }
+ update(input);
+ return doFinal();
+ }
+
+ /**
+ * Resets this <code>Mac</code> object.
+ *
+ * <p>A call to this method resets this <code>Mac</code> object to the
+ * state it was in when previously initialized via a call to
+ * <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ * That is, the object is reset and available to generate another MAC from
+ * the same key, if desired, via new calls to <code>update</code> and
+ * <code>doFinal</code>.
+ * (In order to reuse this <code>Mac</code> object with a different key,
+ * it must be reinitialized via a call to <code>init(Key)</code> or
+ * <code>init(Key, AlgorithmParameterSpec)</code>.
+ */
+ public final void reset() {
+ chooseFirstProvider();
+ spi.engineReset();
+ }
+
+ /**
+ * Returns a clone if the provider implementation is cloneable.
+ *
+ * @return a clone if the provider implementation is cloneable.
+ *
+ * @exception CloneNotSupportedException if this is called on a
+ * delegate that does not support <code>Cloneable</code>.
+ */
+ public final Object clone() throws CloneNotSupportedException {
+ chooseFirstProvider();
+ Mac that = (Mac)super.clone();
+ that.spi = (MacSpi)this.spi.clone();
+ return that;
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/MacSpi.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/MacSpi.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/MacSpi.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,153 @@
+/*
+ * Copyright 1998-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.*;
+import java.security.spec.*;
+
+import java.nio.ByteBuffer;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>Mac</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular MAC algorithm.
+ *
+ * <p> Implementations are free to implement the Cloneable interface.
+ *
+ * @author Jan Luehe
+ *
+ * @since 1.4
+ */
+
+public abstract class MacSpi {
+
+ /**
+ * Returns the length of the MAC in bytes.
+ *
+ * @return the MAC length in bytes.
+ */
+ protected abstract int engineGetMacLength();
+
+ /**
+ * Initializes the MAC with the given (secret) key and algorithm
+ * parameters.
+ *
+ * @param key the (secret) key.
+ * @param params the algorithm parameters.
+ *
+ * @exception InvalidKeyException if the given key is inappropriate for
+ * initializing this MAC.
+ * @exception InvalidAlgorithmParameterException if the given algorithm
+ * parameters are inappropriate for this MAC.
+ */
+ protected abstract void engineInit(Key key,
+ AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException ;
+
+ /**
+ * Processes the given byte.
+ *
+ * @param input the input byte to be processed.
+ */
+ protected abstract void engineUpdate(byte input);
+
+ /**
+ * Processes the first <code>len</code> bytes in <code>input</code>,
+ * starting at <code>offset</code> inclusive.
+ *
+ * @param input the input buffer.
+ * @param offset the offset in <code>input</code> where the input starts.
+ * @param len the number of bytes to process.
+ */
+ protected abstract void engineUpdate(byte[] input, int offset, int len);
+
+ /**
+ * Processes <code>input.remaining()</code> bytes in the ByteBuffer
+ * <code>input</code>, starting at <code>input.position()</code>.
+ * Upon return, the buffer's position will be equal to its limit;
+ * its limit will not have changed.
+ *
+ * <p>Subclasses should consider overriding this method if they can
+ * process ByteBuffers more efficiently than byte arrays.
+ *
+ * @param input the ByteBuffer
+ * @since 1.5
+ */
+ protected void engineUpdate(ByteBuffer input) {
+ if (input.hasRemaining() == false) {
+ return;
+ }
+ if (input.hasArray()) {
+ byte[] b = input.array();
+ int ofs = input.arrayOffset();
+ int pos = input.position();
+ int lim = input.limit();
+ engineUpdate(b, ofs + pos, lim - pos);
+ input.position(lim);
+ } else {
+ int len = input.remaining();
+ byte[] b = new byte[CipherSpi.getTempArraySize(len)];
+ while (len > 0) {
+ int chunk = Math.min(len, b.length);
+ input.get(b, 0, chunk);
+ engineUpdate(b, 0, chunk);
+ len -= chunk;
+ }
+ }
+ }
+
+ /**
+ * Completes the MAC computation and resets the MAC for further use,
+ * maintaining the secret key that the MAC was initialized with.
+ *
+ * @return the MAC result.
+ */
+ protected abstract byte[] engineDoFinal();
+
+ /**
+ * Resets the MAC for further use, maintaining the secret key that the
+ * MAC was initialized with.
+ */
+ protected abstract void engineReset();
+
+ /**
+ * Returns a clone if the implementation is cloneable.
+ *
+ * @return a clone if the implementation is cloneable.
+ *
+ * @exception CloneNotSupportedException if this is called
+ * on an implementation that does not support <code>Cloneable</code>.
+ */
+ public Object clone() throws CloneNotSupportedException {
+ if (this instanceof Cloneable) {
+ return super.clone();
+ } else {
+ throw new CloneNotSupportedException();
+ }
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/NoSuchPaddingException.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/NoSuchPaddingException.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/NoSuchPaddingException.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,61 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This exception is thrown when a particular padding mechanism is
+ * requested but is not available in the environment.
+ *
+ * @author Jan Luehe
+ *
+ * @since 1.4
+ */
+
+public class NoSuchPaddingException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -4572885201200175466L;
+
+ /**
+ * Constructs a NoSuchPaddingException with no detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ */
+ public NoSuchPaddingException() {
+ super();
+ }
+
+ /**
+ * Constructs a NoSuchPaddingException with the specified
+ * detail message.
+ *
+ * @param msg the detail message.
+ */
+ public NoSuchPaddingException(String msg) {
+ super(msg);
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/NullCipher.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/NullCipher.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/NullCipher.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+/**
+ * The NullCipher class is a class that provides an
+ * "identity cipher" -- one that does not tranform the plaintext. As
+ * a consequence, the ciphertext is identical to the plaintext. All
+ * initialization methods do nothing, while the blocksize is set to 1
+ * byte.
+ *
+ * @author Li Gong
+ * @since 1.4
+ */
+
+public class NullCipher extends Cipher {
+
+ public NullCipher() {
+ super(new NullCipherSpi(), null);
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/NullCipherSpi.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/NullCipherSpi.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/NullCipherSpi.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,113 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.*;
+import java.security.spec.*;
+
+/**
+ * This class provides a delegate for the identity cipher - one that does not
+ * tranform the plaintext.
+ *
+ * @author Li Gong
+ * @see Nullcipher
+ *
+ * @since 1.4
+ */
+
+final class NullCipherSpi extends CipherSpi {
+
+ /*
+ * Do not let anybody instantiate this directly (protected).
+ */
+ protected NullCipherSpi() {}
+
+ public void engineSetMode(String mode) {}
+
+ public void engineSetPadding(String padding) {}
+
+ protected int engineGetBlockSize() {
+ return 1;
+ }
+
+ protected int engineGetOutputSize(int inputLen) {
+ return inputLen;
+ }
+
+ protected byte[] engineGetIV() {
+ byte[] x = new byte[8];
+ return x;
+ }
+
+ protected AlgorithmParameters engineGetParameters() {
+ return null;
+ }
+
+ protected void engineInit(int mode, Key key, SecureRandom random) {}
+
+ protected void engineInit(int mode, Key key,
+ AlgorithmParameterSpec params,
+ SecureRandom random) {}
+
+ protected void engineInit(int mode, Key key,
+ AlgorithmParameters params,
+ SecureRandom random) {}
+
+ protected byte[] engineUpdate(byte[] input, int inputOffset,
+ int inputLen) {
+ if (input == null) return null;
+ byte[] x = new byte[inputLen];
+ System.arraycopy(input, inputOffset, x, 0, inputLen);
+ return x;
+ }
+
+ protected int engineUpdate(byte[] input, int inputOffset,
+ int inputLen, byte[] output,
+ int outputOffset) {
+ if (input == null) return 0;
+ System.arraycopy(input, inputOffset, output, outputOffset, inputLen);
+ return inputLen;
+ }
+
+ protected byte[] engineDoFinal(byte[] input, int inputOffset,
+ int inputLen)
+ {
+ return engineUpdate(input, inputOffset, inputLen);
+ }
+
+ protected int engineDoFinal(byte[] input, int inputOffset,
+ int inputLen, byte[] output,
+ int outputOffset)
+ {
+ return engineUpdate(input, inputOffset, inputLen,
+ output, outputOffset);
+ }
+
+ protected int engineGetKeySize(Key key)
+ {
+ return 0;
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/SealedObject.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/SealedObject.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/SealedObject.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,497 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.io.*;
+import java.security.AlgorithmParameters;
+import java.security.Key;
+import java.security.InvalidKeyException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+/**
+ * This class enables a programmer to create an object and protect its
+ * confidentiality with a cryptographic algorithm.
+ *
+ * <p> Given any Serializable object, one can create a SealedObject
+ * that encapsulates the original object, in serialized
+ * format (i.e., a "deep copy"), and seals (encrypts) its serialized contents,
+ * using a cryptographic algorithm such as DES, to protect its
+ * confidentiality. The encrypted content can later be decrypted (with
+ * the corresponding algorithm using the correct decryption key) and
+ * de-serialized, yielding the original object.
+ *
+ * <p> Note that the Cipher object must be fully initialized with the
+ * correct algorithm, key, padding scheme, etc., before being applied
+ * to a SealedObject.
+ *
+ * <p> The original object that was sealed can be recovered in two different
+ * ways: <p>
+ *
+ * <ul>
+ *
+ * <li>by using the {@link #getObject(javax.crypto.Cipher) getObject}
+ * method that takes a <code>Cipher</code> object.
+ *
+ * <p> This method requires a fully initialized <code>Cipher</code> object,
+ * initialized with the
+ * exact same algorithm, key, padding scheme, etc., that were used to seal the
+ * object.
+ *
+ * <p> This approach has the advantage that the party who unseals the
+ * sealed object does not require knowledge of the decryption key. For example,
+ * after one party has initialized the cipher object with the required
+ * decryption key, it could hand over the cipher object to
+ * another party who then unseals the sealed object.
+ *
+ * <p>
+ *
+ * <li>by using one of the
+ * {@link #getObject(java.security.Key) getObject} methods
+ * that take a <code>Key</code> object.
+ *
+ * <p> In this approach, the <code>getObject</code> method creates a cipher
+ * object for the appropriate decryption algorithm and initializes it with the
+ * given decryption key and the algorithm parameters (if any) that were stored
+ * in the sealed object.
+ *
+ * <p> This approach has the advantage that the party who
+ * unseals the object does not need to keep track of the parameters (e.g., an
+ * IV) that were used to seal the object.
+ *
+ * </ul>
+ *
+ * @author Li Gong
+ * @author Jan Luehe
+ * @see Cipher
+ * @since 1.4
+ */
+
+public class SealedObject implements Serializable {
+
+ static final long serialVersionUID = 4482838265551344752L;
+
+ /**
+ * The serialized object contents in encrypted format.
+ *
+ * @serial
+ */
+ private byte[] encryptedContent = null;
+
+ /**
+ * The algorithm that was used to seal this object.
+ *
+ * @serial
+ */
+ private String sealAlg = null;
+
+ /**
+ * The algorithm of the parameters used.
+ *
+ * @serial
+ */
+ private String paramsAlg = null;
+
+ /**
+ * The cryptographic parameters used by the sealing Cipher,
+ * encoded in the default format.
+ * <p>
+ * That is, <code>cipher.getParameters().getEncoded()</code>.
+ *
+ * @serial
+ */
+ protected byte[] encodedParams = null;
+
+ /**
+ * Constructs a SealedObject from any Serializable object.
+ *
+ * <p>The given object is serialized, and its serialized contents are
+ * encrypted using the given Cipher, which must be fully initialized.
+ *
+ * <p>Any algorithm parameters that may be used in the encryption
+ * operation are stored inside of the new <code>SealedObject</code>.
+ *
+ * @param object the object to be sealed; can be null.
+ * @param c the cipher used to seal the object.
+ *
+ * @exception NullPointerException if the given cipher is null.
+ * @exception IOException if an error occurs during serialization
+ * @exception IllegalBlockSizeException if the given cipher is a block
+ * cipher, no padding has been requested, and the total input length
+ * (i.e., the length of the serialized object contents) is not a multiple
+ * of the cipher's block size
+ */
+ public SealedObject(Serializable object, Cipher c) throws IOException,
+ IllegalBlockSizeException
+ {
+ /*
+ * Serialize the object
+ */
+
+ // creating a stream pipe-line, from a to b
+ ByteArrayOutputStream b = new ByteArrayOutputStream();
+ ObjectOutput a = new ObjectOutputStream(b);
+ byte[] content;
+ try {
+ // write and flush the object content to byte array
+ a.writeObject(object);
+ a.flush();
+ content = b.toByteArray();
+ } finally {
+ a.close();
+ }
+
+ /*
+ * Seal the object
+ */
+ try {
+ this.encryptedContent = c.doFinal(content);
+ }
+ catch (BadPaddingException ex) {
+ // if sealing is encryption only
+ // Should never happen??
+ }
+
+ // Save the parameters
+ if (c.getParameters() != null) {
+ this.encodedParams = c.getParameters().getEncoded();
+ this.paramsAlg = c.getParameters().getAlgorithm();
+ }
+
+ // Save the encryption algorithm
+ this.sealAlg = c.getAlgorithm();
+ }
+
+ /**
+ * Constructs a SealedObject object from the passed-in SealedObject.
+ *
+ * @param so a SealedObject object
+ * @exception NullPointerException if the given sealed object is null.
+ */
+ protected SealedObject(SealedObject so) {
+ this.encryptedContent = (byte[]) so.encryptedContent.clone();
+ this.sealAlg = so.sealAlg;
+ this.paramsAlg = so.paramsAlg;
+ if (so.encodedParams != null) {
+ this.encodedParams = (byte[]) so.encodedParams.clone();
+ } else {
+ this.encodedParams = null;
+ }
+ }
+
+ /**
+ * Returns the algorithm that was used to seal this object.
+ *
+ * @return the algorithm that was used to seal this object.
+ */
+ public final String getAlgorithm() {
+ return this.sealAlg;
+ }
+
+ /**
+ * Retrieves the original (encapsulated) object.
+ *
+ * <p>This method creates a cipher for the algorithm that had been used in
+ * the sealing operation.
+ * If the default provider package provides an implementation of that
+ * algorithm, an instance of Cipher containing that implementation is used.
+ * If the algorithm is not available in the default package, other
+ * packages are searched.
+ * The Cipher object is initialized for decryption, using the given
+ * <code>key</code> and the parameters (if any) that had been used in the
+ * sealing operation.
+ *
+ * <p>The encapsulated object is unsealed and de-serialized, before it is
+ * returned.
+ *
+ * @param key the key used to unseal the object.
+ *
+ * @return the original object.
+ *
+ * @exception IOException if an error occurs during de-serialiazation.
+ * @exception ClassNotFoundException if an error occurs during
+ * de-serialiazation.
+ * @exception NoSuchAlgorithmException if the algorithm to unseal the
+ * object is not available.
+ * @exception InvalidKeyException if the given key cannot be used to unseal
+ * the object (e.g., it has the wrong algorithm).
+ * @exception NullPointerException if <code>key</code> is null.
+ */
+ public final Object getObject(Key key)
+ throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
+ InvalidKeyException
+ {
+ if (key == null) {
+ throw new NullPointerException("key is null");
+ }
+
+ try {
+ return unseal(key, null);
+ } catch (NoSuchProviderException nspe) {
+ // we've already caught NoSuchProviderException's and converted
+ // them into NoSuchAlgorithmException's with details about
+ // the failing algorithm
+ throw new NoSuchAlgorithmException("algorithm not found");
+ } catch (IllegalBlockSizeException ibse) {
+ throw new InvalidKeyException(ibse.getMessage());
+ } catch (BadPaddingException bpe) {
+ throw new InvalidKeyException(bpe.getMessage());
+ }
+ }
+
+ /**
+ * Retrieves the original (encapsulated) object.
+ *
+ * <p>The encapsulated object is unsealed (using the given Cipher,
+ * assuming that the Cipher is already properly initialized) and
+ * de-serialized, before it is returned.
+ *
+ * @param c the cipher used to unseal the object
+ *
+ * @return the original object.
+ *
+ * @exception NullPointerException if the given cipher is null.
+ * @exception IOException if an error occurs during de-serialiazation
+ * @exception ClassNotFoundException if an error occurs during
+ * de-serialiazation
+ * @exception IllegalBlockSizeException if the given cipher is a block
+ * cipher, no padding has been requested, and the total input length is
+ * not a multiple of the cipher's block size
+ * @exception BadPaddingException if the given cipher has been
+ * initialized for decryption, and padding has been specified, but
+ * the input data does not have proper expected padding bytes
+ */
+ public final Object getObject(Cipher c)
+ throws IOException, ClassNotFoundException, IllegalBlockSizeException,
+ BadPaddingException
+ {
+ /*
+ * Unseal the object
+ */
+ byte[] content = c.doFinal(this.encryptedContent);
+
+ /*
+ * De-serialize it
+ */
+ // creating a stream pipe-line, from b to a
+ ByteArrayInputStream b = new ByteArrayInputStream(content);
+ ObjectInput a = new extObjectInputStream(b);
+ try {
+ Object obj = a.readObject();
+ return obj;
+ } finally {
+ a.close();
+ }
+ }
+
+ /**
+ * Retrieves the original (encapsulated) object.
+ *
+ * <p>This method creates a cipher for the algorithm that had been used in
+ * the sealing operation, using an implementation of that algorithm from
+ * the given <code>provider</code>.
+ * The Cipher object is initialized for decryption, using the given
+ * <code>key</code> and the parameters (if any) that had been used in the
+ * sealing operation.
+ *
+ * <p>The encapsulated object is unsealed and de-serialized, before it is
+ * returned.
+ *
+ * @param key the key used to unseal the object.
+ * @param provider the name of the provider of the algorithm to unseal
+ * the object.
+ *
+ * @return the original object.
+ *
+ * @exception IllegalArgumentException if the given provider is null
+ * or empty.
+ * @exception IOException if an error occurs during de-serialiazation.
+ * @exception ClassNotFoundException if an error occurs during
+ * de-serialiazation.
+ * @exception NoSuchAlgorithmException if the algorithm to unseal the
+ * object is not available.
+ * @exception NoSuchProviderException if the given provider is not
+ * configured.
+ * @exception InvalidKeyException if the given key cannot be used to unseal
+ * the object (e.g., it has the wrong algorithm).
+ * @exception NullPointerException if <code>key</code> is null.
+ */
+ public final Object getObject(Key key, String provider)
+ throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
+ NoSuchProviderException, InvalidKeyException
+ {
+ if (key == null) {
+ throw new NullPointerException("key is null");
+ }
+ if (provider == null || provider.length() == 0) {
+ throw new IllegalArgumentException("missing provider");
+ }
+
+ try {
+ return unseal(key, provider);
+ } catch (IllegalBlockSizeException ibse) {
+ throw new InvalidKeyException(ibse.getMessage());
+ } catch (BadPaddingException bpe) {
+ throw new InvalidKeyException(bpe.getMessage());
+ }
+ }
+
+
+ private Object unseal(Key key, String provider)
+ throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
+ NoSuchProviderException, InvalidKeyException,
+ IllegalBlockSizeException, BadPaddingException
+ {
+ /*
+ * Create the parameter object.
+ */
+ AlgorithmParameters params = null;
+ if (this.encodedParams != null) {
+ try {
+ if (provider != null)
+ params = AlgorithmParameters.getInstance(this.paramsAlg,
+ provider);
+ else
+ params = AlgorithmParameters.getInstance(this.paramsAlg);
+
+ } catch (NoSuchProviderException nspe) {
+ if (provider == null) {
+ throw new NoSuchAlgorithmException(this.paramsAlg
+ + " not found");
+ } else {
+ throw new NoSuchProviderException(nspe.getMessage());
+ }
+ }
+ params.init(this.encodedParams);
+ }
+
+ /*
+ * Create and initialize the cipher.
+ */
+ Cipher c;
+ try {
+ if (provider != null)
+ c = Cipher.getInstance(this.sealAlg, provider);
+ else
+ c = Cipher.getInstance(this.sealAlg);
+ } catch (NoSuchPaddingException nspe) {
+ throw new NoSuchAlgorithmException("Padding that was used in "
+ + "sealing operation not "
+ + "available");
+ } catch (NoSuchProviderException nspe) {
+ if (provider == null) {
+ throw new NoSuchAlgorithmException(this.sealAlg+" not found");
+ } else {
+ throw new NoSuchProviderException(nspe.getMessage());
+ }
+ }
+
+ try {
+ if (params != null)
+ c.init(Cipher.DECRYPT_MODE, key, params);
+ else
+ c.init(Cipher.DECRYPT_MODE, key);
+ } catch (InvalidAlgorithmParameterException iape) {
+ // this should never happen, because we use the exact same
+ // parameters that were used in the sealing operation
+ throw new RuntimeException(iape.getMessage());
+ }
+
+ /*
+ * Unseal the object
+ */
+ byte[] content = c.doFinal(this.encryptedContent);
+
+ /*
+ * De-serialize it
+ */
+ // creating a stream pipe-line, from b to a
+ ByteArrayInputStream b = new ByteArrayInputStream(content);
+ ObjectInput a = new extObjectInputStream(b);
+ try {
+ Object obj = a.readObject();
+ return obj;
+ } finally {
+ a.close();
+ }
+ }
+
+ /**
+ * Restores the state of the SealedObject from a stream.
+ * @param s the object input stream.
+ * @exception NullPointerException if s is null.
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ if (encryptedContent != null)
+ encryptedContent = (byte[])encryptedContent.clone();
+ if (encodedParams != null)
+ encodedParams = (byte[])encodedParams.clone();
+ }
+}
+
+final class extObjectInputStream extends ObjectInputStream {
+
+ private static ClassLoader systemClassLoader = null;
+
+ extObjectInputStream(InputStream in)
+ throws IOException, StreamCorruptedException {
+ super(in);
+ }
+
+ protected Class resolveClass(ObjectStreamClass v)
+ throws IOException, ClassNotFoundException
+ {
+
+ try {
+ /*
+ * Calling the super.resolveClass() first
+ * will let us pick up bug fixes in the super
+ * class (e.g., 4171142).
+ */
+ return super.resolveClass(v);
+ } catch (ClassNotFoundException cnfe) {
+ /*
+ * This is a workaround for bug 4224921.
+ */
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ if (loader == null) {
+ if (systemClassLoader == null) {
+ systemClassLoader = ClassLoader.getSystemClassLoader();
+ }
+ loader = systemClassLoader;
+ if (loader == null) {
+ throw new ClassNotFoundException(v.getName());
+ }
+ }
+
+ return Class.forName(v.getName(), false, loader);
+ }
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKey.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKey.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKey.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,58 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+/**
+ * A secret (symmetric) key.
+ *
+ * <p>This interface contains no methods or constants.
+ * Its only purpose is to group (and provide type safety for) secret keys.
+ *
+ * <p>Provider implementations of this interface must overwrite the
+ * <code>equals</code> and <code>hashCode</code> methods inherited from
+ * <code>java.lang.Object</code>, so that secret keys are compared based on
+ * their underlying key material and not based on reference.
+ *
+ * <p>Keys that implement this interface return the string <code>RAW</code>
+ * as their encoding format (see <code>getFormat</code>), and return the
+ * raw key bytes as the result of a <code>getEncoded</code> method call. (The
+ * <code>getFormat</code> and <code>getEncoded</code> methods are inherited
+ * from the <code>java.security.Key</code> parent interface.)
+ *
+ * @author Jan Luehe
+ *
+ * @see SecretKeyFactory
+ * @see Cipher
+ * @since 1.4
+ */
+
+public interface SecretKey extends java.security.Key {
+ /**
+ * The class fingerprint that is set to indicate serialization
+ * compatibility since J2SE 1.4.
+ */
+ static final long serialVersionUID = -4795878709595146952L;
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKeyFactory.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKeyFactory.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKeyFactory.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,415 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.util.*;
+
+import java.security.*;
+import java.security.Provider.Service;
+import java.security.spec.*;
+
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class represents a factory for secret keys.
+ *
+ * <P> Key factories are used to convert <I>keys</I> (opaque
+ * cryptographic keys of type <code>Key</code>) into <I>key specifications</I>
+ * (transparent representations of the underlying key material), and vice
+ * versa.
+ * Secret key factories operate only on secret (symmetric) keys.
+ *
+ * <P> Key factories are bi-directional, i.e., they allow to build an opaque
+ * key object from a given key specification (key material), or to retrieve
+ * the underlying key material of a key object in a suitable format.
+ *
+ * <P> Application developers should refer to their provider's documentation
+ * to find out which key specifications are supported by the
+ * {@link #generateSecret(java.security.spec.KeySpec) generateSecret} and
+ * {@link #getKeySpec(javax.crypto.SecretKey, java.lang.Class) getKeySpec}
+ * methods.
+ * For example, the DES secret-key factory supplied by the "SunJCE" provider
+ * supports <code>DESKeySpec</code> as a transparent representation of DES
+ * keys, and that provider's secret-key factory for Triple DES keys supports
+ * <code>DESedeKeySpec</code> as a transparent representation of Triple DES
+ * keys.
+ *
+ * @author Jan Luehe
+ *
+ * @see SecretKey
+ * @see javax.crypto.spec.DESKeySpec
+ * @see javax.crypto.spec.DESedeKeySpec
+ * @see javax.crypto.spec.PBEKeySpec
+ * @since 1.4
+ */
+
+public class SecretKeyFactory {
+
+ // The provider
+ private Provider provider;
+
+ // The algorithm associated with this factory
+ private final String algorithm;
+
+ // The provider implementation (delegate)
+ private volatile SecretKeyFactorySpi spi;
+
+ // lock for mutex during provider selection
+ private final Object lock = new Object();
+
+ // remaining services to try in provider selection
+ // null once provider is selected
+ private Iterator serviceIterator;
+
+ /**
+ * Creates a SecretKeyFactory object.
+ *
+ * @param keyFacSpi the delegate
+ * @param provider the provider
+ * @param algorithm the secret-key algorithm
+ */
+ protected SecretKeyFactory(SecretKeyFactorySpi keyFacSpi,
+ Provider provider, String algorithm) {
+ this.spi = keyFacSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException {
+ this.algorithm = algorithm;
+ List list = GetInstance.getServices("SecretKeyFactory", algorithm);
+ serviceIterator = list.iterator();
+ // fetch and instantiate initial spi
+ if (nextSpi(null) == null) {
+ throw new NoSuchAlgorithmException
+ (algorithm + " SecretKeyFactory not available");
+ }
+ }
+
+ /**
+ * Returns a <code>SecretKeyFactory</code> object that converts
+ * secret keys of the specified algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new SecretKeyFactory object encapsulating the
+ * SecretKeyFactorySpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested secret-key
+ * algorithm.
+ * See Appendix A in the <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new <code>SecretKeyFactory</code> object.
+ *
+ * @exception NullPointerException if the specified algorithm
+ * is null.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * SecretKeyFactorySpi implementation for the
+ * specified algorithm.
+ *
+ * @see java.security.Provider
+ */
+ public static final SecretKeyFactory getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ return new SecretKeyFactory(algorithm);
+ }
+
+ /**
+ * Returns a <code>SecretKeyFactory</code> object that converts
+ * secret keys of the specified algorithm.
+ *
+ * <p> A new SecretKeyFactory object encapsulating the
+ * SecretKeyFactorySpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard name of the requested secret-key
+ * algorithm.
+ * See Appendix A in the <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new <code>SecretKeyFactory</code> object.
+ *
+ * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
+ * implementation for the specified algorithm is not
+ * available from the specified provider.
+ *
+ * @exception NullPointerException if the specified algorithm
+ * is null.
+ *
+ * @throws NoSuchProviderException if the specified provider is not
+ * registered in the security provider list.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static final SecretKeyFactory getInstance(String algorithm,
+ String provider) throws NoSuchAlgorithmException,
+ NoSuchProviderException {
+ Instance instance = JceSecurity.getInstance("SecretKeyFactory",
+ SecretKeyFactorySpi.class, algorithm, provider);
+ return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a <code>SecretKeyFactory</code> object that converts
+ * secret keys of the specified algorithm.
+ *
+ * <p> A new SecretKeyFactory object encapsulating the
+ * SecretKeyFactorySpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * @param algorithm the standard name of the requested secret-key
+ * algorithm.
+ * See Appendix A in the <a href=
+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture Reference Guide</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new <code>SecretKeyFactory</code> object.
+ *
+ * @exception NullPointerException if the specified algorithm
+ * is null.
+ *
+ * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the <code>provider</code>
+ * is null.
+ *
+ * @see java.security.Provider
+ */
+ public static final SecretKeyFactory getInstance(String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Instance instance = JceSecurity.getInstance("SecretKeyFactory",
+ SecretKeyFactorySpi.class, algorithm, provider);
+ return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns the provider of this <code>SecretKeyFactory</code> object.
+ *
+ * @return the provider of this <code>SecretKeyFactory</code> object
+ */
+ public final Provider getProvider() {
+ synchronized (lock) {
+ // disable further failover after this call
+ serviceIterator = null;
+ return provider;
+ }
+ }
+
+ /**
+ * Returns the algorithm name of this <code>SecretKeyFactory</code> object.
+ *
+ * <p>This is the same name that was specified in one of the
+ * <code>getInstance</code> calls that created this
+ * <code>SecretKeyFactory</code> object.
+ *
+ * @return the algorithm name of this <code>SecretKeyFactory</code>
+ * object.
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Update the active spi of this class and return the next
+ * implementation for failover. If no more implemenations are
+ * available, this method returns null. However, the active spi of
+ * this class is never set to null.
+ */
+ private SecretKeyFactorySpi nextSpi(SecretKeyFactorySpi oldSpi) {
+ synchronized (lock) {
+ // somebody else did a failover concurrently
+ // try that spi now
+ if ((oldSpi != null) && (oldSpi != spi)) {
+ return spi;
+ }
+ if (serviceIterator == null) {
+ return null;
+ }
+ while (serviceIterator.hasNext()) {
+ Service s = (Service)serviceIterator.next();
+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
+ continue;
+ }
+ try {
+ Object obj = s.newInstance(null);
+ if (obj instanceof SecretKeyFactorySpi == false) {
+ continue;
+ }
+ SecretKeyFactorySpi spi = (SecretKeyFactorySpi)obj;
+ provider = s.getProvider();
+ this.spi = spi;
+ return spi;
+ } catch (NoSuchAlgorithmException e) {
+ // ignore
+ }
+ }
+ serviceIterator = null;
+ return null;
+ }
+ }
+
+ /**
+ * Generates a <code>SecretKey</code> object from the provided key
+ * specification (key material).
+ *
+ * @param keySpec the specification (key material) of the secret key
+ *
+ * @return the secret key
+ *
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this secret-key factory to produce a secret key.
+ */
+ public final SecretKey generateSecret(KeySpec keySpec)
+ throws InvalidKeySpecException {
+ if (serviceIterator == null) {
+ return spi.engineGenerateSecret(keySpec);
+ }
+ Exception failure = null;
+ SecretKeyFactorySpi mySpi = spi;
+ do {
+ try {
+ return mySpi.engineGenerateSecret(keySpec);
+ } catch (Exception e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi);
+ }
+ } while (mySpi != null);
+ if (failure instanceof InvalidKeySpecException) {
+ throw (InvalidKeySpecException)failure;
+ }
+ throw new InvalidKeySpecException
+ ("Could not generate secret key", failure);
+ }
+
+ /**
+ * Returns a specification (key material) of the given key object
+ * in the requested format.
+ *
+ * @param key the key
+ * @param keySpec the requested format in which the key material shall be
+ * returned
+ *
+ * @return the underlying key specification (key material) in the
+ * requested format
+ *
+ * @exception InvalidKeySpecException if the requested key specification is
+ * inappropriate for the given key (e.g., the algorithms associated with
+ * <code>key</code> and <code>keySpec</code> do not match, or
+ * <code>key</code> references a key on a cryptographic hardware device
+ * whereas <code>keySpec</code> is the specification of a software-based
+ * key), or the given key cannot be dealt with
+ * (e.g., the given key has an algorithm or format not supported by this
+ * secret-key factory).
+ */
+ public final KeySpec getKeySpec(SecretKey key, Class keySpec)
+ throws InvalidKeySpecException {
+ if (serviceIterator == null) {
+ return spi.engineGetKeySpec(key, keySpec);
+ }
+ Exception failure = null;
+ SecretKeyFactorySpi mySpi = spi;
+ do {
+ try {
+ return mySpi.engineGetKeySpec(key, keySpec);
+ } catch (Exception e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi);
+ }
+ } while (mySpi != null);
+ if (failure instanceof InvalidKeySpecException) {
+ throw (InvalidKeySpecException)failure;
+ }
+ throw new InvalidKeySpecException
+ ("Could not get key spec", failure);
+ }
+
+ /**
+ * Translates a key object, whose provider may be unknown or potentially
+ * untrusted, into a corresponding key object of this secret-key factory.
+ *
+ * @param key the key whose provider is unknown or untrusted
+ *
+ * @return the translated key
+ *
+ * @exception InvalidKeyException if the given key cannot be processed
+ * by this secret-key factory.
+ */
+ public final SecretKey translateKey(SecretKey key)
+ throws InvalidKeyException {
+ if (serviceIterator == null) {
+ return spi.engineTranslateKey(key);
+ }
+ Exception failure = null;
+ SecretKeyFactorySpi mySpi = spi;
+ do {
+ try {
+ return mySpi.engineTranslateKey(key);
+ } catch (Exception e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi);
+ }
+ } while (mySpi != null);
+ if (failure instanceof InvalidKeyException) {
+ throw (InvalidKeyException)failure;
+ }
+ throw new InvalidKeyException
+ ("Could not translate key", failure);
+ }
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKeyFactorySpi.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKeyFactorySpi.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/SecretKeyFactorySpi.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,108 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.*;
+import java.security.spec.*;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the <code>SecretKeyFactory</code> class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a secret-key factory for a particular algorithm.
+ *
+ * <P> A provider should document all the key specifications supported by its
+ * secret key factory.
+ * For example, the DES secret-key factory supplied by the "SunJCE" provider
+ * supports <code>DESKeySpec</code> as a transparent representation of DES
+ * keys, and that provider's secret-key factory for Triple DES keys supports
+ * <code>DESedeKeySpec</code> as a transparent representation of Triple DES
+ * keys.
+ *
+ * @author Jan Luehe
+ *
+ * @see SecretKey
+ * @see javax.crypto.spec.DESKeySpec
+ * @see javax.crypto.spec.DESedeKeySpec
+ * @since 1.4
+ */
+
+public abstract class SecretKeyFactorySpi {
+
+ /**
+ * Generates a <code>SecretKey</code> object from the
+ * provided key specification (key material).
+ *
+ * @param keySpec the specification (key material) of the secret key
+ *
+ * @return the secret key
+ *
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this secret-key factory to produce a secret key.
+ */
+ protected abstract SecretKey engineGenerateSecret(KeySpec keySpec)
+ throws InvalidKeySpecException;
+
+ /**
+ * Returns a specification (key material) of the given key
+ * object in the requested format.
+ *
+ * @param key the key
+ *
+ * @param keySpec the requested format in which the key material shall be
+ * returned
+ *
+ * @return the underlying key specification (key material) in the
+ * requested format
+ *
+ * @exception InvalidKeySpecException if the requested key specification is
+ * inappropriate for the given key (e.g., the algorithms associated with
+ * <code>key</code> and <code>keySpec</code> do not match, or
+ * <code>key</code> references a key on a cryptographic hardware device
+ * whereas <code>keySpec</code> is the specification of a software-based
+ * key), or the given key cannot be dealt with
+ * (e.g., the given key has an algorithm or format not supported by this
+ * secret-key factory).
+ */
+ protected abstract KeySpec engineGetKeySpec(SecretKey key, Class keySpec)
+ throws InvalidKeySpecException;
+
+ /**
+ * Translates a key object, whose provider may be unknown or
+ * potentially untrusted, into a corresponding key object of this
+ * secret-key factory.
+ *
+ * @param key the key whose provider is unknown or untrusted
+ *
+ * @return the translated key
+ *
+ * @exception InvalidKeyException if the given key cannot be processed
+ * by this secret-key factory.
+ */
+ protected abstract SecretKey engineTranslateKey(SecretKey key)
+ throws InvalidKeyException;
+}
Added: openjdk-crypto/trunk/src/main/java/javax/crypto/ShortBufferException.java
===================================================================
--- openjdk-crypto/trunk/src/main/java/javax/crypto/ShortBufferException.java (rev 0)
+++ openjdk-crypto/trunk/src/main/java/javax/crypto/ShortBufferException.java 2010-03-13 04:23:29 UTC (rev 25)
@@ -0,0 +1,61 @@
+/*
+ * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.crypto;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This exception is thrown when an output buffer provided by the user
+ * is too short to hold the operation result.
+ *
+ * @author Jan Luehe
+ *
+ * @since 1.4
+ */
+
+public class ShortBufferException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 8427718640832943747L;
+
+ /**
+ * Constructs a ShortBufferException with no detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ */
+ public ShortBufferException() {
+ super();
+ }
+
+ /**
+ * Constructs a ShortBufferException with the specified
+ * detail message.
+ *
+ * @param msg the detail message.
+ */
+ public ShortBufferException(String msg) {
+ super(msg);
+ }
+}
More information about the pkg-eucalyptus-commits
mailing list