移植 sunpkcs11
This commit is contained in:
commit
e4ca64c640
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
||||||
|
/.idea/.gitignore
|
||||||
|
/.idea/encodings.xml
|
||||||
|
/.idea/misc.xml
|
17
pom.xml
Normal file
17
pom.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.sunyard</groupId>
|
||||||
|
<artifactId>JceOnPkcs11</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
7
src/main/java/com/sunyard/Main.java
Normal file
7
src/main/java/com/sunyard/Main.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package com.sunyard;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello, World!");
|
||||||
|
}
|
||||||
|
}
|
1018
src/main/java/com/sunyard/security/pkcs11/Config.java
Normal file
1018
src/main/java/com/sunyard/security/pkcs11/Config.java
Normal file
File diff suppressed because it is too large
Load Diff
103
src/main/java/com/sunyard/security/pkcs11/KeyCache.java
Normal file
103
src/main/java/com/sunyard/security/pkcs11/KeyCache.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.lang.ref.*;
|
||||||
|
|
||||||
|
import java.security.Key;
|
||||||
|
|
||||||
|
import sun.security.util.Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key to P11Key translation cache. The PKCS#11 token can only perform
|
||||||
|
* operations on keys stored on the token (permanently or temporarily). That
|
||||||
|
* means that in order to allow the PKCS#11 provider to use keys from other
|
||||||
|
* providers, we need to transparently convert them to P11Keys. The engines
|
||||||
|
* do that using (Secret)KeyFactories, which in turn use this class as a
|
||||||
|
* cache.
|
||||||
|
*
|
||||||
|
* There are two KeyCache instances per provider, one for secret keys and
|
||||||
|
* one for public and private keys.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class KeyCache {
|
||||||
|
|
||||||
|
private final Cache<IdentityWrapper, P11Key> strongCache;
|
||||||
|
|
||||||
|
private WeakReference<Map<Key,P11Key>> cacheReference;
|
||||||
|
|
||||||
|
KeyCache() {
|
||||||
|
strongCache = Cache.newHardMemoryCache(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class IdentityWrapper {
|
||||||
|
final Object obj;
|
||||||
|
IdentityWrapper(Object obj) {
|
||||||
|
this.obj = obj;
|
||||||
|
}
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o instanceof IdentityWrapper == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IdentityWrapper other = (IdentityWrapper)o;
|
||||||
|
return this.obj == other.obj;
|
||||||
|
}
|
||||||
|
public int hashCode() {
|
||||||
|
return System.identityHashCode(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized P11Key get(Key key) {
|
||||||
|
P11Key p11Key = strongCache.get(new IdentityWrapper(key));
|
||||||
|
if (p11Key != null) {
|
||||||
|
return p11Key;
|
||||||
|
}
|
||||||
|
Map<Key,P11Key> map =
|
||||||
|
(cacheReference == null) ? null : cacheReference.get();
|
||||||
|
if (map == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void put(Key key, P11Key p11Key) {
|
||||||
|
strongCache.put(new IdentityWrapper(key), p11Key);
|
||||||
|
Map<Key,P11Key> map =
|
||||||
|
(cacheReference == null) ? null : cacheReference.get();
|
||||||
|
if (map == null) {
|
||||||
|
map = new IdentityHashMap<>();
|
||||||
|
cacheReference = new WeakReference<>(map);
|
||||||
|
}
|
||||||
|
map.put(key, p11Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special interface for additional MessageDigestSpi method(s).
|
||||||
|
*/
|
||||||
|
public interface MessageDigestSpi2 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the digest using the specified key.
|
||||||
|
* This is used for SSL 3.0 only, we may deprecate and remove the support
|
||||||
|
* of this in the future
|
||||||
|
*
|
||||||
|
* @param key the key whose value is to be digested.
|
||||||
|
*/
|
||||||
|
void engineUpdate(SecretKey key) throws InvalidKeyException;
|
||||||
|
}
|
776
src/main/java/com/sunyard/security/pkcs11/P11AEADCipher.java
Normal file
776
src/main/java/com/sunyard/security/pkcs11/P11AEADCipher.java
Normal file
@ -0,0 +1,776 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import sun.nio.ch.DirectBuffer;
|
||||||
|
import sun.security.jca.JCAUtil;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P11 AEAD Cipher implementation class. This class currently supports
|
||||||
|
* AES with GCM mode.
|
||||||
|
*
|
||||||
|
* Note that AEAD modes do not use padding, so this class does not have
|
||||||
|
* its own padding impl. In addition, NSS CKM_AES_GCM only supports single-part
|
||||||
|
* encryption/decryption, thus the current impl uses PKCS#11 C_Encrypt/C_Decrypt
|
||||||
|
* calls and buffers data until doFinal is called.
|
||||||
|
*
|
||||||
|
* Note that PKCS#11 standard currently only supports GCM and CCM AEAD modes.
|
||||||
|
* There are no provisions for other AEAD modes yet.
|
||||||
|
*
|
||||||
|
* @since 13
|
||||||
|
*/
|
||||||
|
final class P11AEADCipher extends CipherSpi {
|
||||||
|
|
||||||
|
// mode constant for GCM mode
|
||||||
|
private static final int MODE_GCM = 10;
|
||||||
|
|
||||||
|
// default constants for GCM
|
||||||
|
private static final int GCM_DEFAULT_TAG_LEN = 16;
|
||||||
|
private static final int GCM_DEFAULT_IV_LEN = 16;
|
||||||
|
|
||||||
|
private static final String ALGO = "AES";
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private final long mechanism;
|
||||||
|
|
||||||
|
// mode, one of MODE_* above
|
||||||
|
private final int blockMode;
|
||||||
|
|
||||||
|
// acceptable key size, -1 if more than 1 key sizes are accepted
|
||||||
|
private final int fixedKeySize;
|
||||||
|
|
||||||
|
// associated session, if any
|
||||||
|
private Session session = null;
|
||||||
|
|
||||||
|
// key, if init() was called
|
||||||
|
private P11Key p11Key = null;
|
||||||
|
|
||||||
|
// flag indicating whether an operation is initialized
|
||||||
|
private boolean initialized = false;
|
||||||
|
|
||||||
|
// falg indicating encrypt or decrypt mode
|
||||||
|
private boolean encrypt = true;
|
||||||
|
|
||||||
|
// parameters
|
||||||
|
private byte[] iv = null;
|
||||||
|
private int tagLen = -1;
|
||||||
|
private SecureRandom random = JCAUtil.getSecureRandom();
|
||||||
|
|
||||||
|
// dataBuffer is cleared upon doFinal calls
|
||||||
|
private ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream();
|
||||||
|
// aadBuffer is cleared upon successful init calls
|
||||||
|
private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream();
|
||||||
|
private boolean updateCalled = false;
|
||||||
|
|
||||||
|
private boolean requireReinit = false;
|
||||||
|
private P11Key lastEncKey = null;
|
||||||
|
private byte[] lastEncIv = null;
|
||||||
|
|
||||||
|
P11AEADCipher(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception, NoSuchAlgorithmException {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
|
||||||
|
String[] algoParts = algorithm.split("/");
|
||||||
|
if (algoParts.length != 3) {
|
||||||
|
throw new ProviderException("Unsupported Transformation format: " +
|
||||||
|
algorithm);
|
||||||
|
}
|
||||||
|
if (!algoParts[0].startsWith("AES")) {
|
||||||
|
throw new ProviderException("Only support AES for AEAD cipher mode");
|
||||||
|
}
|
||||||
|
int index = algoParts[0].indexOf('_');
|
||||||
|
if (index != -1) {
|
||||||
|
// should be well-formed since we specify what we support
|
||||||
|
fixedKeySize = Integer.parseInt(algoParts[0].substring(index+1)) >> 3;
|
||||||
|
} else {
|
||||||
|
fixedKeySize = -1;
|
||||||
|
}
|
||||||
|
this.blockMode = parseMode(algoParts[1]);
|
||||||
|
if (!algoParts[2].equals("NoPadding")) {
|
||||||
|
throw new ProviderException("Only NoPadding is supported for AEAD cipher mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
|
||||||
|
// Disallow change of mode for now since currently it's explicitly
|
||||||
|
// defined in transformation strings
|
||||||
|
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseMode(String mode) throws NoSuchAlgorithmException {
|
||||||
|
mode = mode.toUpperCase(Locale.ENGLISH);
|
||||||
|
int result;
|
||||||
|
if (mode.equals("GCM")) {
|
||||||
|
result = MODE_GCM;
|
||||||
|
} else {
|
||||||
|
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineSetPadding(String padding)
|
||||||
|
throws NoSuchPaddingException {
|
||||||
|
// Disallow change of padding for now since currently it's explicitly
|
||||||
|
// defined in transformation strings
|
||||||
|
throw new NoSuchPaddingException("Unsupported padding " + padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineGetBlockSize() {
|
||||||
|
return 16; // constant; only AES is supported
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineGetOutputSize(int inputLen) {
|
||||||
|
return doFinalLength(inputLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineGetIV() {
|
||||||
|
return (iv == null) ? null : iv.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected AlgorithmParameters engineGetParameters() {
|
||||||
|
if (encrypt && iv == null && tagLen == -1) {
|
||||||
|
switch (blockMode) {
|
||||||
|
case MODE_GCM:
|
||||||
|
iv = new byte[GCM_DEFAULT_IV_LEN];
|
||||||
|
tagLen = GCM_DEFAULT_TAG_LEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unsupported mode");
|
||||||
|
}
|
||||||
|
random.nextBytes(iv);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
AlgorithmParameterSpec spec;
|
||||||
|
String apAlgo;
|
||||||
|
switch (blockMode) {
|
||||||
|
case MODE_GCM:
|
||||||
|
apAlgo = "GCM";
|
||||||
|
spec = new GCMParameterSpec(tagLen << 3, iv);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unsupported mode");
|
||||||
|
}
|
||||||
|
AlgorithmParameters params =
|
||||||
|
AlgorithmParameters.getInstance(apAlgo);
|
||||||
|
params.init(spec);
|
||||||
|
return params;
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
// NoSuchAlgorithmException, NoSuchProviderException
|
||||||
|
// InvalidParameterSpecException
|
||||||
|
throw new ProviderException("Could not encode parameters", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(int opmode, Key key, SecureRandom sr)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
if (opmode == Cipher.DECRYPT_MODE) {
|
||||||
|
throw new InvalidKeyException("Parameters required for decryption");
|
||||||
|
}
|
||||||
|
updateCalled = false;
|
||||||
|
try {
|
||||||
|
implInit(opmode, key, null, -1, sr);
|
||||||
|
} catch (InvalidAlgorithmParameterException e) {
|
||||||
|
throw new InvalidKeyException("init() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(int opmode, Key key,
|
||||||
|
AlgorithmParameterSpec params, SecureRandom sr)
|
||||||
|
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||||
|
if (opmode == Cipher.DECRYPT_MODE && params == null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Parameters required for decryption");
|
||||||
|
}
|
||||||
|
updateCalled = false;
|
||||||
|
byte[] ivValue = null;
|
||||||
|
int tagLen = -1;
|
||||||
|
if (params != null) {
|
||||||
|
switch (blockMode) {
|
||||||
|
case MODE_GCM:
|
||||||
|
if (!(params instanceof GCMParameterSpec)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Only GCMParameterSpec is supported");
|
||||||
|
}
|
||||||
|
ivValue = ((GCMParameterSpec) params).getIV();
|
||||||
|
tagLen = ((GCMParameterSpec) params).getTLen() >> 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unsupported mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
implInit(opmode, key, ivValue, tagLen, sr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
|
||||||
|
SecureRandom sr)
|
||||||
|
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||||
|
if (opmode == Cipher.DECRYPT_MODE && params == null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Parameters required for decryption");
|
||||||
|
}
|
||||||
|
updateCalled = false;
|
||||||
|
try {
|
||||||
|
AlgorithmParameterSpec paramSpec = null;
|
||||||
|
if (params != null) {
|
||||||
|
switch (blockMode) {
|
||||||
|
case MODE_GCM:
|
||||||
|
paramSpec =
|
||||||
|
params.getParameterSpec(GCMParameterSpec.class);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unsupported mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
engineInit(opmode, key, paramSpec, sr);
|
||||||
|
} catch (InvalidParameterSpecException ex) {
|
||||||
|
throw new InvalidAlgorithmParameterException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// actual init() implementation
|
||||||
|
private void implInit(int opmode, Key key, byte[] iv, int tagLen,
|
||||||
|
SecureRandom sr)
|
||||||
|
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||||
|
reset(true);
|
||||||
|
if (fixedKeySize != -1 &&
|
||||||
|
((key instanceof P11Key) ? ((P11Key) key).length() >> 3 :
|
||||||
|
key.getEncoded().length) != fixedKeySize) {
|
||||||
|
throw new InvalidKeyException("Key size is invalid");
|
||||||
|
}
|
||||||
|
P11Key newKey = P11SecretKeyFactory.convertKey(token, key, ALGO);
|
||||||
|
switch (opmode) {
|
||||||
|
case Cipher.ENCRYPT_MODE:
|
||||||
|
encrypt = true;
|
||||||
|
requireReinit = Arrays.equals(iv, lastEncIv) &&
|
||||||
|
(newKey == lastEncKey);
|
||||||
|
if (requireReinit) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Cannot reuse iv for GCM encryption");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Cipher.DECRYPT_MODE:
|
||||||
|
encrypt = false;
|
||||||
|
requireReinit = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Unsupported mode: " + opmode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// decryption without parameters is checked in all engineInit() calls
|
||||||
|
if (sr != null) {
|
||||||
|
this.random = sr;
|
||||||
|
}
|
||||||
|
if (iv == null && tagLen == -1) {
|
||||||
|
// generate default values
|
||||||
|
switch (blockMode) {
|
||||||
|
case MODE_GCM:
|
||||||
|
iv = new byte[GCM_DEFAULT_IV_LEN];
|
||||||
|
this.random.nextBytes(iv);
|
||||||
|
tagLen = GCM_DEFAULT_TAG_LEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unsupported mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.iv = iv;
|
||||||
|
this.tagLen = tagLen;
|
||||||
|
this.p11Key = newKey;
|
||||||
|
try {
|
||||||
|
initialize();
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not initialize cipher", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelOperation() {
|
||||||
|
// cancel operation by finishing it; avoid killSession as some
|
||||||
|
// hardware vendors may require re-login
|
||||||
|
int bufLen = doFinalLength(0);
|
||||||
|
byte[] buffer = new byte[bufLen];
|
||||||
|
byte[] in = dataBuffer.toByteArray();
|
||||||
|
int inLen = in.length;
|
||||||
|
try {
|
||||||
|
if (encrypt) {
|
||||||
|
token.p11.C_Encrypt(session.id(), 0, in, 0, inLen,
|
||||||
|
0, buffer, 0, bufLen);
|
||||||
|
} else {
|
||||||
|
token.p11.C_Decrypt(session.id(), 0, in, 0, inLen,
|
||||||
|
0, buffer, 0, bufLen);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
if (e.getErrorCode() == CKR_OPERATION_NOT_INITIALIZED) {
|
||||||
|
// Cancel Operation may be invoked after an error on a PKCS#11
|
||||||
|
// call. If the operation inside the token was already cancelled,
|
||||||
|
// do not fail here. This is part of a defensive mechanism for
|
||||||
|
// PKCS#11 libraries that do not strictly follow the standard.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (encrypt) {
|
||||||
|
throw new ProviderException("Cancel failed", e);
|
||||||
|
}
|
||||||
|
// ignore failure for decryption
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureInitialized() throws PKCS11Exception {
|
||||||
|
if (initialized && aadBuffer.size() > 0) {
|
||||||
|
// need to cancel first to avoid CKR_OPERATION_ACTIVE
|
||||||
|
reset(true);
|
||||||
|
}
|
||||||
|
if (!initialized) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() throws PKCS11Exception {
|
||||||
|
if (p11Key == null) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"Operation cannot be performed without"
|
||||||
|
+ " calling engineInit first");
|
||||||
|
}
|
||||||
|
if (requireReinit) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Must use either different key or iv for GCM encryption");
|
||||||
|
}
|
||||||
|
|
||||||
|
token.ensureValid();
|
||||||
|
|
||||||
|
byte[] aad = (aadBuffer.size() > 0? aadBuffer.toByteArray() : null);
|
||||||
|
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
CK_MECHANISM mechWithParams;
|
||||||
|
switch (blockMode) {
|
||||||
|
case MODE_GCM:
|
||||||
|
mechWithParams = new CK_MECHANISM(mechanism,
|
||||||
|
new CK_GCM_PARAMS(tagLen << 3, iv, aad));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unsupported mode: " + blockMode);
|
||||||
|
}
|
||||||
|
if (session == null) {
|
||||||
|
session = token.getOpSession();
|
||||||
|
}
|
||||||
|
if (encrypt) {
|
||||||
|
token.p11.C_EncryptInit(session.id(), mechWithParams,
|
||||||
|
p11KeyID);
|
||||||
|
} else {
|
||||||
|
token.p11.C_DecryptInit(session.id(), mechWithParams,
|
||||||
|
p11KeyID);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
dataBuffer.reset();
|
||||||
|
aadBuffer.reset();
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if doFinal(inLen) is called, how big does the output buffer have to be?
|
||||||
|
private int doFinalLength(int inLen) {
|
||||||
|
if (inLen < 0) {
|
||||||
|
throw new ProviderException("Invalid negative input length");
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = inLen + dataBuffer.size();
|
||||||
|
if (encrypt) {
|
||||||
|
result += tagLen;
|
||||||
|
} else {
|
||||||
|
// PKCS11Exception: CKR_BUFFER_TOO_SMALL
|
||||||
|
//result -= tagLen;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the states to the pre-initialized values
|
||||||
|
private void reset(boolean doCancel) {
|
||||||
|
if (!initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCancel && token.explicitCancel) {
|
||||||
|
cancelOperation();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
dataBuffer.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
|
||||||
|
updateCalled = true;
|
||||||
|
int n = implUpdate(in, inOfs, inLen);
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
|
||||||
|
int outOfs) throws ShortBufferException {
|
||||||
|
updateCalled = true;
|
||||||
|
implUpdate(in, inOfs, inLen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
@Override
|
||||||
|
protected int engineUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
|
||||||
|
throws ShortBufferException {
|
||||||
|
updateCalled = true;
|
||||||
|
implUpdate(inBuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
@Override
|
||||||
|
protected synchronized void engineUpdateAAD(byte[] src, int srcOfs, int srcLen)
|
||||||
|
throws IllegalStateException {
|
||||||
|
if ((src == null) || (srcOfs < 0) || (srcOfs + srcLen > src.length)) {
|
||||||
|
throw new IllegalArgumentException("Invalid AAD");
|
||||||
|
}
|
||||||
|
if (requireReinit) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Must use either different key or iv for GCM encryption");
|
||||||
|
}
|
||||||
|
if (p11Key == null) {
|
||||||
|
throw new IllegalStateException("Need to initialize Cipher first");
|
||||||
|
}
|
||||||
|
if (updateCalled) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Update has been called; no more AAD data");
|
||||||
|
}
|
||||||
|
aadBuffer.write(src, srcOfs, srcLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
@Override
|
||||||
|
protected void engineUpdateAAD(ByteBuffer src)
|
||||||
|
throws IllegalStateException {
|
||||||
|
if (src == null) {
|
||||||
|
throw new IllegalArgumentException("Invalid AAD");
|
||||||
|
}
|
||||||
|
byte[] srcBytes = new byte[src.remaining()];
|
||||||
|
src.get(srcBytes);
|
||||||
|
engineUpdateAAD(srcBytes, 0, srcBytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
|
||||||
|
throws IllegalBlockSizeException, BadPaddingException {
|
||||||
|
int minOutLen = doFinalLength(inLen);
|
||||||
|
try {
|
||||||
|
byte[] out = new byte[minOutLen];
|
||||||
|
int n = engineDoFinal(in, inOfs, inLen, out, 0);
|
||||||
|
return P11Util.convert(out, 0, n);
|
||||||
|
} catch (ShortBufferException e) {
|
||||||
|
// convert since the output length is calculated by doFinalLength()
|
||||||
|
throw new ProviderException(e);
|
||||||
|
} finally {
|
||||||
|
updateCalled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
|
||||||
|
int outOfs) throws ShortBufferException, IllegalBlockSizeException,
|
||||||
|
BadPaddingException {
|
||||||
|
try {
|
||||||
|
return implDoFinal(in, inOfs, inLen, out, outOfs, out.length - outOfs);
|
||||||
|
} finally {
|
||||||
|
updateCalled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
@Override
|
||||||
|
protected int engineDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer)
|
||||||
|
throws ShortBufferException, IllegalBlockSizeException,
|
||||||
|
BadPaddingException {
|
||||||
|
try {
|
||||||
|
return implDoFinal(inBuffer, outBuffer);
|
||||||
|
} finally {
|
||||||
|
updateCalled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int implUpdate(byte[] in, int inOfs, int inLen) {
|
||||||
|
if (inLen > 0) {
|
||||||
|
updateCalled = true;
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
reset(false);
|
||||||
|
throw new ProviderException("update() failed", e);
|
||||||
|
}
|
||||||
|
dataBuffer.write(in, inOfs, inLen);
|
||||||
|
}
|
||||||
|
// always 0 as NSS only supports single-part encryption/decryption
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int implUpdate(ByteBuffer inBuf) {
|
||||||
|
int inLen = inBuf.remaining();
|
||||||
|
if (inLen > 0) {
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
reset(false);
|
||||||
|
throw new ProviderException("update() failed", e);
|
||||||
|
}
|
||||||
|
byte[] data = new byte[inLen];
|
||||||
|
inBuf.get(data);
|
||||||
|
dataBuffer.write(data, 0, data.length);
|
||||||
|
}
|
||||||
|
// always 0 as NSS only supports single-part encryption/decryption
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int implDoFinal(byte[] in, int inOfs, int inLen,
|
||||||
|
byte[] out, int outOfs, int outLen)
|
||||||
|
throws ShortBufferException, IllegalBlockSizeException,
|
||||||
|
BadPaddingException {
|
||||||
|
int requiredOutLen = doFinalLength(inLen);
|
||||||
|
if (outLen < requiredOutLen) {
|
||||||
|
throw new ShortBufferException();
|
||||||
|
}
|
||||||
|
boolean doCancel = true;
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
if (dataBuffer.size() > 0) {
|
||||||
|
if (in != null && inOfs > 0 && inLen > 0 &&
|
||||||
|
inOfs < (in.length - inLen)) {
|
||||||
|
dataBuffer.write(in, inOfs, inLen);
|
||||||
|
}
|
||||||
|
in = dataBuffer.toByteArray();
|
||||||
|
inOfs = 0;
|
||||||
|
inLen = in.length;
|
||||||
|
}
|
||||||
|
int k = 0;
|
||||||
|
if (encrypt) {
|
||||||
|
k = token.p11.C_Encrypt(session.id(), 0, in, inOfs, inLen,
|
||||||
|
0, out, outOfs, outLen);
|
||||||
|
doCancel = false;
|
||||||
|
} else {
|
||||||
|
// Special handling to match SunJCE provider behavior
|
||||||
|
if (inLen == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
k = token.p11.C_Decrypt(session.id(), 0, in, inOfs, inLen,
|
||||||
|
0, out, outOfs, outLen);
|
||||||
|
doCancel = false;
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only
|
||||||
|
// keep the operation active on CKR_BUFFER_TOO_SMALL errors or
|
||||||
|
// successful calls to determine the output length. However,
|
||||||
|
// these cases are not expected here because the output length
|
||||||
|
// is checked in the OpenJDK side before making the PKCS#11 call.
|
||||||
|
// Thus, doCancel can safely be 'false'.
|
||||||
|
doCancel = false;
|
||||||
|
handleException(e);
|
||||||
|
throw new ProviderException("doFinal() failed", e);
|
||||||
|
} finally {
|
||||||
|
if (encrypt) {
|
||||||
|
lastEncKey = this.p11Key;
|
||||||
|
lastEncIv = this.iv;
|
||||||
|
requireReinit = true;
|
||||||
|
}
|
||||||
|
reset(doCancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int implDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer)
|
||||||
|
throws ShortBufferException, IllegalBlockSizeException,
|
||||||
|
BadPaddingException {
|
||||||
|
int outLen = outBuffer.remaining();
|
||||||
|
int inLen = inBuffer.remaining();
|
||||||
|
|
||||||
|
int requiredOutLen = doFinalLength(inLen);
|
||||||
|
if (outLen < requiredOutLen) {
|
||||||
|
throw new ShortBufferException();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean doCancel = true;
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
|
||||||
|
long inAddr = 0;
|
||||||
|
byte[] in = null;
|
||||||
|
int inOfs = 0;
|
||||||
|
if (dataBuffer.size() > 0) {
|
||||||
|
if (inLen > 0) {
|
||||||
|
byte[] temp = new byte[inLen];
|
||||||
|
inBuffer.get(temp);
|
||||||
|
dataBuffer.write(temp, 0, temp.length);
|
||||||
|
}
|
||||||
|
in = dataBuffer.toByteArray();
|
||||||
|
inOfs = 0;
|
||||||
|
inLen = in.length;
|
||||||
|
} else {
|
||||||
|
if (inBuffer instanceof DirectBuffer) {
|
||||||
|
inAddr = ((DirectBuffer) inBuffer).address();
|
||||||
|
inOfs = inBuffer.position();
|
||||||
|
} else {
|
||||||
|
if (inBuffer.hasArray()) {
|
||||||
|
in = inBuffer.array();
|
||||||
|
inOfs = inBuffer.position() + inBuffer.arrayOffset();
|
||||||
|
} else {
|
||||||
|
in = new byte[inLen];
|
||||||
|
inBuffer.get(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long outAddr = 0;
|
||||||
|
byte[] outArray = null;
|
||||||
|
int outOfs = 0;
|
||||||
|
if (outBuffer instanceof DirectBuffer) {
|
||||||
|
outAddr = ((DirectBuffer) outBuffer).address();
|
||||||
|
outOfs = outBuffer.position();
|
||||||
|
} else {
|
||||||
|
if (outBuffer.hasArray()) {
|
||||||
|
outArray = outBuffer.array();
|
||||||
|
outOfs = outBuffer.position() + outBuffer.arrayOffset();
|
||||||
|
} else {
|
||||||
|
outArray = new byte[outLen];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
if (encrypt) {
|
||||||
|
k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen,
|
||||||
|
outAddr, outArray, outOfs, outLen);
|
||||||
|
doCancel = false;
|
||||||
|
} else {
|
||||||
|
// Special handling to match SunJCE provider behavior
|
||||||
|
if (inLen == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen,
|
||||||
|
outAddr, outArray, outOfs, outLen);
|
||||||
|
doCancel = false;
|
||||||
|
}
|
||||||
|
outBuffer.position(outBuffer.position() + k);
|
||||||
|
return k;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only
|
||||||
|
// keep the operation active on CKR_BUFFER_TOO_SMALL errors or
|
||||||
|
// successful calls to determine the output length. However,
|
||||||
|
// these cases are not expected here because the output length
|
||||||
|
// is checked in the OpenJDK side before making the PKCS#11 call.
|
||||||
|
// Thus, doCancel can safely be 'false'.
|
||||||
|
doCancel = false;
|
||||||
|
handleException(e);
|
||||||
|
throw new ProviderException("doFinal() failed", e);
|
||||||
|
} finally {
|
||||||
|
if (encrypt) {
|
||||||
|
lastEncKey = this.p11Key;
|
||||||
|
lastEncIv = this.iv;
|
||||||
|
requireReinit = true;
|
||||||
|
}
|
||||||
|
reset(doCancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleException(PKCS11Exception e)
|
||||||
|
throws ShortBufferException, IllegalBlockSizeException,
|
||||||
|
BadPaddingException {
|
||||||
|
long errorCode = e.getErrorCode();
|
||||||
|
if (errorCode == CKR_BUFFER_TOO_SMALL) {
|
||||||
|
throw (ShortBufferException)
|
||||||
|
(new ShortBufferException().initCause(e));
|
||||||
|
} else if (errorCode == CKR_DATA_LEN_RANGE ||
|
||||||
|
errorCode == CKR_ENCRYPTED_DATA_LEN_RANGE) {
|
||||||
|
throw (IllegalBlockSizeException)
|
||||||
|
(new IllegalBlockSizeException(e.toString()).initCause(e));
|
||||||
|
} else if (errorCode == CKR_ENCRYPTED_DATA_INVALID ||
|
||||||
|
// Solaris-specific
|
||||||
|
errorCode == CKR_GENERAL_ERROR) {
|
||||||
|
throw (BadPaddingException)
|
||||||
|
(new BadPaddingException(e.toString()).initCause(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
|
||||||
|
InvalidKeyException {
|
||||||
|
// XXX key wrapping
|
||||||
|
throw new UnsupportedOperationException("engineWrap()");
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
|
||||||
|
int wrappedKeyType)
|
||||||
|
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||||
|
// XXX key unwrapping
|
||||||
|
throw new UnsupportedOperationException("engineUnwrap()");
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
@Override
|
||||||
|
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||||
|
int n = P11SecretKeyFactory.convertKey
|
||||||
|
(token, key, ALGO).length();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1021
src/main/java/com/sunyard/security/pkcs11/P11Cipher.java
Normal file
1021
src/main/java/com/sunyard/security/pkcs11/P11Cipher.java
Normal file
File diff suppressed because it is too large
Load Diff
273
src/main/java/com/sunyard/security/pkcs11/P11DHKeyFactory.java
Normal file
273
src/main/java/com/sunyard/security/pkcs11/P11DHKeyFactory.java
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import javax.crypto.interfaces.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DH KeyFactory implementation.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11DHKeyFactory extends P11KeyFactory {
|
||||||
|
|
||||||
|
P11DHKeyFactory(Token token, String algorithm) {
|
||||||
|
super(token, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
if (key instanceof DHPublicKey) {
|
||||||
|
DHPublicKey dhKey = (DHPublicKey)key;
|
||||||
|
DHParameterSpec params = dhKey.getParams();
|
||||||
|
return generatePublic(
|
||||||
|
dhKey.getY(),
|
||||||
|
params.getP(),
|
||||||
|
params.getG()
|
||||||
|
);
|
||||||
|
} else if ("X.509".equals(key.getFormat())) {
|
||||||
|
// let SunJCE provider parse for us, then recurse
|
||||||
|
try {
|
||||||
|
KeyFactory factory = implGetSoftwareFactory();
|
||||||
|
key = (PublicKey)factory.translateKey(key);
|
||||||
|
return implTranslatePublicKey(key);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeyException("Could not translate key", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("PublicKey must be instance "
|
||||||
|
+ "of DHPublicKey or have X.509 encoding");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create DH public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateKey implTranslatePrivateKey(PrivateKey key)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
if (key instanceof DHPrivateKey) {
|
||||||
|
DHPrivateKey dhKey = (DHPrivateKey)key;
|
||||||
|
DHParameterSpec params = dhKey.getParams();
|
||||||
|
return generatePrivate(
|
||||||
|
dhKey.getX(),
|
||||||
|
params.getP(),
|
||||||
|
params.getG()
|
||||||
|
);
|
||||||
|
} else if ("PKCS#8".equals(key.getFormat())) {
|
||||||
|
// let SunJCE provider parse for us, then recurse
|
||||||
|
try {
|
||||||
|
KeyFactory factory = implGetSoftwareFactory();
|
||||||
|
key = (PrivateKey)factory.translateKey(key);
|
||||||
|
return implTranslatePrivateKey(key);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeyException("Could not translate key", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("PrivateKey must be instance "
|
||||||
|
+ "of DHPrivateKey or have PKCS#8 encoding");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create DH private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected PublicKey engineGeneratePublic(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec instanceof X509EncodedKeySpec) {
|
||||||
|
try {
|
||||||
|
KeyFactory factory = implGetSoftwareFactory();
|
||||||
|
PublicKey key = factory.generatePublic(keySpec);
|
||||||
|
return implTranslatePublicKey(key);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create DH public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keySpec instanceof DHPublicKeySpec == false) {
|
||||||
|
throw new InvalidKeySpecException("Only DHPublicKeySpec and "
|
||||||
|
+ "X509EncodedKeySpec supported for DH public keys");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
DHPublicKeySpec ds = (DHPublicKeySpec)keySpec;
|
||||||
|
return generatePublic(
|
||||||
|
ds.getY(),
|
||||||
|
ds.getP(),
|
||||||
|
ds.getG()
|
||||||
|
);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create DH public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||||
|
try {
|
||||||
|
KeyFactory factory = implGetSoftwareFactory();
|
||||||
|
PrivateKey key = factory.generatePrivate(keySpec);
|
||||||
|
return implTranslatePrivateKey(key);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create DH private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keySpec instanceof DHPrivateKeySpec == false) {
|
||||||
|
throw new InvalidKeySpecException("Only DHPrivateKeySpec and "
|
||||||
|
+ "PKCS8EncodedKeySpec supported for DH private keys");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
DHPrivateKeySpec ds = (DHPrivateKeySpec)keySpec;
|
||||||
|
return generatePrivate(
|
||||||
|
ds.getX(),
|
||||||
|
ds.getP(),
|
||||||
|
ds.getG()
|
||||||
|
);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create DH private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicKey generatePublic(BigInteger y, BigInteger p, BigInteger g)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE, y),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME, p),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE, g),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PUBLIC_KEY, CKK_DH, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.publicKey
|
||||||
|
(session, keyID, "DH", p.bitLength(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PrivateKey generatePrivate(BigInteger x, BigInteger p,
|
||||||
|
BigInteger g) throws PKCS11Exception {
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DH),
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE, x),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME, p),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE, g),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PRIVATE_KEY, CKK_DH, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.privateKey
|
||||||
|
(session, keyID, "DH", p.bitLength(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException {
|
||||||
|
if (keySpec.isAssignableFrom(DHPublicKeySpec.class)) {
|
||||||
|
session[0] = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE),
|
||||||
|
};
|
||||||
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
KeySpec spec = new DHPublicKeySpec(
|
||||||
|
attributes[0].getBigInteger(),
|
||||||
|
attributes[1].getBigInteger(),
|
||||||
|
attributes[2].getBigInteger()
|
||||||
|
);
|
||||||
|
return keySpec.cast(spec);
|
||||||
|
} else { // X.509 handled in superclass
|
||||||
|
throw new InvalidKeySpecException("Only DHPublicKeySpec and "
|
||||||
|
+ "X509EncodedKeySpec supported for DH public keys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException {
|
||||||
|
if (keySpec.isAssignableFrom(DHPrivateKeySpec.class)) {
|
||||||
|
session[0] = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE),
|
||||||
|
};
|
||||||
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
KeySpec spec = new DHPrivateKeySpec(
|
||||||
|
attributes[0].getBigInteger(),
|
||||||
|
attributes[1].getBigInteger(),
|
||||||
|
attributes[2].getBigInteger()
|
||||||
|
);
|
||||||
|
return keySpec.cast(spec);
|
||||||
|
} else { // PKCS#8 handled in superclass
|
||||||
|
throw new InvalidKeySpecException("Only DHPrivateKeySpec "
|
||||||
|
+ "and PKCS8EncodedKeySpec supported for DH private keys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
|
||||||
|
return KeyFactory.getInstance("DH", P11Util.getSunJceProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
273
src/main/java/com/sunyard/security/pkcs11/P11DSAKeyFactory.java
Normal file
273
src/main/java/com/sunyard/security/pkcs11/P11DSAKeyFactory.java
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DSA KeyFactory implementation.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11DSAKeyFactory extends P11KeyFactory {
|
||||||
|
|
||||||
|
P11DSAKeyFactory(Token token, String algorithm) {
|
||||||
|
super(token, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
if (key instanceof DSAPublicKey) {
|
||||||
|
DSAPublicKey dsaKey = (DSAPublicKey)key;
|
||||||
|
DSAParams params = dsaKey.getParams();
|
||||||
|
return generatePublic(
|
||||||
|
dsaKey.getY(),
|
||||||
|
params.getP(),
|
||||||
|
params.getQ(),
|
||||||
|
params.getG()
|
||||||
|
);
|
||||||
|
} else if ("X.509".equals(key.getFormat())) {
|
||||||
|
// let Sun provider parse for us, then recurse
|
||||||
|
byte[] encoded = key.getEncoded();
|
||||||
|
key = new sun.security.provider.DSAPublicKey(encoded);
|
||||||
|
return implTranslatePublicKey(key);
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("PublicKey must be instance "
|
||||||
|
+ "of DSAPublicKey or have X.509 encoding");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create DSA public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateKey implTranslatePrivateKey(PrivateKey key)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
if (key instanceof DSAPrivateKey) {
|
||||||
|
DSAPrivateKey dsaKey = (DSAPrivateKey)key;
|
||||||
|
DSAParams params = dsaKey.getParams();
|
||||||
|
return generatePrivate(
|
||||||
|
dsaKey.getX(),
|
||||||
|
params.getP(),
|
||||||
|
params.getQ(),
|
||||||
|
params.getG()
|
||||||
|
);
|
||||||
|
} else if ("PKCS#8".equals(key.getFormat())) {
|
||||||
|
// let Sun provider parse for us, then recurse
|
||||||
|
byte[] encoded = key.getEncoded();
|
||||||
|
key = new sun.security.provider.DSAPrivateKey(encoded);
|
||||||
|
return implTranslatePrivateKey(key);
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("PrivateKey must be instance "
|
||||||
|
+ "of DSAPrivateKey or have PKCS#8 encoding");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create DSA private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected PublicKey engineGeneratePublic(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec instanceof X509EncodedKeySpec) {
|
||||||
|
try {
|
||||||
|
byte[] encoded = ((X509EncodedKeySpec)keySpec).getEncoded();
|
||||||
|
PublicKey key = new sun.security.provider.DSAPublicKey(encoded);
|
||||||
|
return implTranslatePublicKey(key);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create DSA public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keySpec instanceof DSAPublicKeySpec == false) {
|
||||||
|
throw new InvalidKeySpecException("Only DSAPublicKeySpec and "
|
||||||
|
+ "X509EncodedKeySpec supported for DSA public keys");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
DSAPublicKeySpec ds = (DSAPublicKeySpec)keySpec;
|
||||||
|
return generatePublic(
|
||||||
|
ds.getY(),
|
||||||
|
ds.getP(),
|
||||||
|
ds.getQ(),
|
||||||
|
ds.getG()
|
||||||
|
);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create DSA public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||||
|
try {
|
||||||
|
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
|
||||||
|
PrivateKey key = new sun.security.provider.DSAPrivateKey(encoded);
|
||||||
|
return implTranslatePrivateKey(key);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create DSA private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keySpec instanceof DSAPrivateKeySpec == false) {
|
||||||
|
throw new InvalidKeySpecException("Only DSAPrivateKeySpec and "
|
||||||
|
+ "PKCS8EncodedKeySpec supported for DSA private keys");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
DSAPrivateKeySpec ds = (DSAPrivateKeySpec)keySpec;
|
||||||
|
return generatePrivate(
|
||||||
|
ds.getX(),
|
||||||
|
ds.getP(),
|
||||||
|
ds.getQ(),
|
||||||
|
ds.getG()
|
||||||
|
);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create DSA private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicKey generatePublic(BigInteger y, BigInteger p, BigInteger q,
|
||||||
|
BigInteger g) throws PKCS11Exception {
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DSA),
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE, y),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME, p),
|
||||||
|
new CK_ATTRIBUTE(CKA_SUBPRIME, q),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE, g),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PUBLIC_KEY, CKK_DSA, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.publicKey
|
||||||
|
(session, keyID, "DSA", p.bitLength(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PrivateKey generatePrivate(BigInteger x, BigInteger p,
|
||||||
|
BigInteger q, BigInteger g) throws PKCS11Exception {
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_DSA),
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE, x),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME, p),
|
||||||
|
new CK_ATTRIBUTE(CKA_SUBPRIME, q),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE, g),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PRIVATE_KEY, CKK_DSA, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.privateKey
|
||||||
|
(session, keyID, "DSA", p.bitLength(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException {
|
||||||
|
if (keySpec.isAssignableFrom(DSAPublicKeySpec.class)) {
|
||||||
|
session[0] = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME),
|
||||||
|
new CK_ATTRIBUTE(CKA_SUBPRIME),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE),
|
||||||
|
};
|
||||||
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
KeySpec spec = new DSAPublicKeySpec(
|
||||||
|
attributes[0].getBigInteger(),
|
||||||
|
attributes[1].getBigInteger(),
|
||||||
|
attributes[2].getBigInteger(),
|
||||||
|
attributes[3].getBigInteger()
|
||||||
|
);
|
||||||
|
return keySpec.cast(spec);
|
||||||
|
} else { // X.509 handled in superclass
|
||||||
|
throw new InvalidKeySpecException("Only DSAPublicKeySpec and "
|
||||||
|
+ "X509EncodedKeySpec supported for DSA public keys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException {
|
||||||
|
if (keySpec.isAssignableFrom(DSAPrivateKeySpec.class)) {
|
||||||
|
session[0] = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME),
|
||||||
|
new CK_ATTRIBUTE(CKA_SUBPRIME),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE),
|
||||||
|
};
|
||||||
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
KeySpec spec = new DSAPrivateKeySpec(
|
||||||
|
attributes[0].getBigInteger(),
|
||||||
|
attributes[1].getBigInteger(),
|
||||||
|
attributes[2].getBigInteger(),
|
||||||
|
attributes[3].getBigInteger()
|
||||||
|
);
|
||||||
|
return keySpec.cast(spec);
|
||||||
|
} else { // PKCS#8 handled in superclass
|
||||||
|
throw new InvalidKeySpecException("Only DSAPrivateKeySpec "
|
||||||
|
+ "and PKCS8EncodedKeySpec supported for DSA private keys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
|
||||||
|
return KeyFactory.getInstance("DSA", P11Util.getSunProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
331
src/main/java/com/sunyard/security/pkcs11/P11Digest.java
Normal file
331
src/main/java/com/sunyard/security/pkcs11/P11Digest.java
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
|
import sun.nio.ch.DirectBuffer;
|
||||||
|
|
||||||
|
//import sun.security.util.MessageDigestSpi2;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MessageDigest implementation class. This class currently supports
|
||||||
|
* MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512.
|
||||||
|
*
|
||||||
|
* Note that many digest operations are on fairly small amounts of data
|
||||||
|
* (less than 100 bytes total). For example, the 2nd hashing in HMAC or
|
||||||
|
* the PRF in TLS. In order to speed those up, we use some buffering to
|
||||||
|
* minimize number of the Java->native transitions.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11Digest extends MessageDigestSpi implements Cloneable,
|
||||||
|
MessageDigestSpi2 {
|
||||||
|
|
||||||
|
/* fields initialized, no session acquired */
|
||||||
|
private final static int S_BLANK = 1;
|
||||||
|
|
||||||
|
/* data in buffer, session acquired, but digest not initialized */
|
||||||
|
private final static int S_BUFFERED = 2;
|
||||||
|
|
||||||
|
/* session initialized for digesting */
|
||||||
|
private final static int S_INIT = 3;
|
||||||
|
|
||||||
|
private final static int BUFFER_SIZE = 96;
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id object
|
||||||
|
private final CK_MECHANISM mechanism;
|
||||||
|
|
||||||
|
// length of the digest in bytes
|
||||||
|
private final int digestLength;
|
||||||
|
|
||||||
|
// associated session, if any
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
// current state, one of S_* above
|
||||||
|
private int state;
|
||||||
|
|
||||||
|
// buffer to reduce number of JNI calls
|
||||||
|
private byte[] buffer;
|
||||||
|
|
||||||
|
// offset into the buffer
|
||||||
|
private int bufOfs;
|
||||||
|
|
||||||
|
P11Digest(Token token, String algorithm, long mechanism) {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = new CK_MECHANISM(mechanism);
|
||||||
|
switch ((int)mechanism) {
|
||||||
|
case (int)CKM_MD2:
|
||||||
|
case (int)CKM_MD5:
|
||||||
|
digestLength = 16;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA_1:
|
||||||
|
digestLength = 20;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA224:
|
||||||
|
case (int)CKM_SHA512_224:
|
||||||
|
digestLength = 28;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA256:
|
||||||
|
case (int)CKM_SHA512_256:
|
||||||
|
digestLength = 32;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA384:
|
||||||
|
digestLength = 48;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA512:
|
||||||
|
digestLength = 64;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unknown mechanism: " + mechanism);
|
||||||
|
}
|
||||||
|
buffer = new byte[BUFFER_SIZE];
|
||||||
|
state = S_BLANK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected int engineGetDigestLength() {
|
||||||
|
return digestLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchSession() {
|
||||||
|
token.ensureValid();
|
||||||
|
if (state == S_BLANK) {
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
state = S_BUFFERED;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("No more session available", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected void engineReset() {
|
||||||
|
token.ensureValid();
|
||||||
|
|
||||||
|
if (session != null) {
|
||||||
|
if (state == S_INIT && token.explicitCancel == true
|
||||||
|
&& session.hasObjects() == false) {
|
||||||
|
session = token.killSession(session);
|
||||||
|
} else {
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state = S_BLANK;
|
||||||
|
bufOfs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected byte[] engineDigest() {
|
||||||
|
try {
|
||||||
|
byte[] digest = new byte[digestLength];
|
||||||
|
int n = engineDigest(digest, 0, digestLength);
|
||||||
|
return digest;
|
||||||
|
} catch (DigestException e) {
|
||||||
|
throw new ProviderException("internal error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected int engineDigest(byte[] digest, int ofs, int len)
|
||||||
|
throws DigestException {
|
||||||
|
if (len < digestLength) {
|
||||||
|
throw new DigestException("Length must be at least " +
|
||||||
|
digestLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSession();
|
||||||
|
try {
|
||||||
|
int n;
|
||||||
|
if (state == S_BUFFERED) {
|
||||||
|
n = token.p11.C_DigestSingle(session.id(), mechanism, buffer, 0,
|
||||||
|
bufOfs, digest, ofs, len);
|
||||||
|
bufOfs = 0;
|
||||||
|
} else {
|
||||||
|
if (bufOfs != 0) {
|
||||||
|
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0,
|
||||||
|
bufOfs);
|
||||||
|
bufOfs = 0;
|
||||||
|
}
|
||||||
|
n = token.p11.C_DigestFinal(session.id(), digest, ofs, len);
|
||||||
|
}
|
||||||
|
if (n != digestLength) {
|
||||||
|
throw new ProviderException("internal digest length error");
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("digest() failed", e);
|
||||||
|
} finally {
|
||||||
|
engineReset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected void engineUpdate(byte in) {
|
||||||
|
byte[] temp = { in };
|
||||||
|
engineUpdate(temp, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected void engineUpdate(byte[] in, int ofs, int len) {
|
||||||
|
if (len <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSession();
|
||||||
|
try {
|
||||||
|
if (state == S_BUFFERED) {
|
||||||
|
token.p11.C_DigestInit(session.id(), mechanism);
|
||||||
|
state = S_INIT;
|
||||||
|
}
|
||||||
|
if ((bufOfs != 0) && (bufOfs + len > buffer.length)) {
|
||||||
|
// process the buffered data
|
||||||
|
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
|
||||||
|
bufOfs = 0;
|
||||||
|
}
|
||||||
|
if (bufOfs + len > buffer.length) {
|
||||||
|
// process the new data
|
||||||
|
token.p11.C_DigestUpdate(session.id(), 0, in, ofs, len);
|
||||||
|
} else {
|
||||||
|
// buffer the new data
|
||||||
|
System.arraycopy(in, ofs, buffer, bufOfs, len);
|
||||||
|
bufOfs += len;
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
engineReset();
|
||||||
|
throw new ProviderException("update() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by SunJSSE via reflection during the SSL 3.0 handshake if
|
||||||
|
// the master secret is sensitive.
|
||||||
|
// Note: Change to protected after this method is moved from
|
||||||
|
// sun.security.util.MessageSpi2 interface to
|
||||||
|
// java.security.MessageDigestSpi class
|
||||||
|
public void engineUpdate(SecretKey key) throws InvalidKeyException {
|
||||||
|
// SunJSSE calls this method only if the key does not have a RAW
|
||||||
|
// encoding, i.e. if it is sensitive. Therefore, no point in calling
|
||||||
|
// SecretKeyFactory to try to convert it. Just verify it ourselves.
|
||||||
|
if (key instanceof P11Key == false) {
|
||||||
|
throw new InvalidKeyException("Not a P11Key: " + key);
|
||||||
|
}
|
||||||
|
P11Key p11Key = (P11Key)key;
|
||||||
|
if (p11Key.token != token) {
|
||||||
|
throw new InvalidKeyException("Not a P11Key of this provider: " +
|
||||||
|
key);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSession();
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
if (state == S_BUFFERED) {
|
||||||
|
token.p11.C_DigestInit(session.id(), mechanism);
|
||||||
|
state = S_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufOfs != 0) {
|
||||||
|
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
|
||||||
|
bufOfs = 0;
|
||||||
|
}
|
||||||
|
token.p11.C_DigestKey(session.id(), p11KeyID);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
engineReset();
|
||||||
|
throw new ProviderException("update(SecretKey) failed", e);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected void engineUpdate(ByteBuffer byteBuffer) {
|
||||||
|
int len = byteBuffer.remaining();
|
||||||
|
if (len <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byteBuffer instanceof DirectBuffer == false) {
|
||||||
|
super.engineUpdate(byteBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchSession();
|
||||||
|
long addr = ((DirectBuffer)byteBuffer).address();
|
||||||
|
int ofs = byteBuffer.position();
|
||||||
|
try {
|
||||||
|
if (state == S_BUFFERED) {
|
||||||
|
token.p11.C_DigestInit(session.id(), mechanism);
|
||||||
|
state = S_INIT;
|
||||||
|
}
|
||||||
|
if (bufOfs != 0) {
|
||||||
|
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
|
||||||
|
bufOfs = 0;
|
||||||
|
}
|
||||||
|
token.p11.C_DigestUpdate(session.id(), addr + ofs, null, 0, len);
|
||||||
|
byteBuffer.position(ofs + len);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
engineReset();
|
||||||
|
throw new ProviderException("update() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
P11Digest copy = (P11Digest) super.clone();
|
||||||
|
copy.buffer = buffer.clone();
|
||||||
|
try {
|
||||||
|
if (session != null) {
|
||||||
|
copy.session = copy.token.getOpSession();
|
||||||
|
}
|
||||||
|
if (state == S_INIT) {
|
||||||
|
byte[] stateValues =
|
||||||
|
token.p11.C_GetOperationState(session.id());
|
||||||
|
token.p11.C_SetOperationState(copy.session.id(),
|
||||||
|
stateValues, 0, 0);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw (CloneNotSupportedException)
|
||||||
|
(new CloneNotSupportedException(algorithm).initCause(e));
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.ECPublicKey;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyAgreement implementation for ECDH.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
final class P11ECDHKeyAgreement extends KeyAgreementSpi {
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private final long mechanism;
|
||||||
|
|
||||||
|
// private key, if initialized
|
||||||
|
private P11Key privateKey;
|
||||||
|
|
||||||
|
// encoded public point, non-null between doPhase() and generateSecret() only
|
||||||
|
private byte[] publicValue;
|
||||||
|
|
||||||
|
// length of the secret to be derived
|
||||||
|
private int secretLen;
|
||||||
|
|
||||||
|
P11ECDHKeyAgreement(Token token, String algorithm, long mechanism) {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(Key key, SecureRandom random)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
if (key instanceof PrivateKey == false) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key must be instance of PrivateKey");
|
||||||
|
}
|
||||||
|
privateKey = P11KeyFactory.convertKey(token, key, "EC");
|
||||||
|
publicValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(Key key, AlgorithmParameterSpec params,
|
||||||
|
SecureRandom random) throws InvalidKeyException,
|
||||||
|
InvalidAlgorithmParameterException {
|
||||||
|
if (params != null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Parameters not supported");
|
||||||
|
}
|
||||||
|
engineInit(key, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected Key engineDoPhase(Key key, boolean lastPhase)
|
||||||
|
throws InvalidKeyException, IllegalStateException {
|
||||||
|
if (privateKey == null) {
|
||||||
|
throw new IllegalStateException("Not initialized");
|
||||||
|
}
|
||||||
|
if (publicValue != null) {
|
||||||
|
throw new IllegalStateException("Phase already executed");
|
||||||
|
}
|
||||||
|
if (lastPhase == false) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Only two party agreement supported, lastPhase must be true");
|
||||||
|
}
|
||||||
|
if (key instanceof ECPublicKey == false) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key must be a PublicKey with algorithm EC");
|
||||||
|
}
|
||||||
|
ECPublicKey ecKey = (ECPublicKey)key;
|
||||||
|
int keyLenBits = ecKey.getParams().getCurve().getField().getFieldSize();
|
||||||
|
secretLen = (keyLenBits + 7) >> 3;
|
||||||
|
publicValue = P11ECKeyFactory.getEncodedPublicValue(ecKey);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineGenerateSecret() throws IllegalStateException {
|
||||||
|
if ((privateKey == null) || (publicValue == null)) {
|
||||||
|
throw new IllegalStateException("Not initialized correctly");
|
||||||
|
}
|
||||||
|
Session session = null;
|
||||||
|
long privKeyID = privateKey.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
|
||||||
|
};
|
||||||
|
CK_ECDH1_DERIVE_PARAMS ckParams =
|
||||||
|
new CK_ECDH1_DERIVE_PARAMS(CKD_NULL, null, publicValue);
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
|
||||||
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism, ckParams), privKeyID,
|
||||||
|
attributes);
|
||||||
|
attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE)
|
||||||
|
};
|
||||||
|
token.p11.C_GetAttributeValue(session.id(), keyID, attributes);
|
||||||
|
byte[] secret = attributes[0].getByteArray();
|
||||||
|
token.p11.C_DestroyObject(session.id(), keyID);
|
||||||
|
return secret;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Could not derive key", e);
|
||||||
|
} finally {
|
||||||
|
privateKey.releaseKeyID();
|
||||||
|
publicValue = null;
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineGenerateSecret(byte[] sharedSecret, int
|
||||||
|
offset) throws IllegalStateException, ShortBufferException {
|
||||||
|
if (offset + secretLen > sharedSecret.length) {
|
||||||
|
throw new ShortBufferException("Need " + secretLen
|
||||||
|
+ " bytes, only " + (sharedSecret.length - offset) + " available");
|
||||||
|
}
|
||||||
|
byte[] secret = engineGenerateSecret();
|
||||||
|
System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
|
||||||
|
return secret.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected SecretKey engineGenerateSecret(String algorithm)
|
||||||
|
throws IllegalStateException, NoSuchAlgorithmException,
|
||||||
|
InvalidKeyException {
|
||||||
|
if (algorithm == null) {
|
||||||
|
throw new NoSuchAlgorithmException("Algorithm must not be null");
|
||||||
|
}
|
||||||
|
if (algorithm.equals("TlsPremasterSecret") == false) {
|
||||||
|
throw new NoSuchAlgorithmException
|
||||||
|
("Only supported for algorithm TlsPremasterSecret");
|
||||||
|
}
|
||||||
|
return nativeGenerateSecret(algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecretKey nativeGenerateSecret(String algorithm)
|
||||||
|
throws IllegalStateException, NoSuchAlgorithmException,
|
||||||
|
InvalidKeyException {
|
||||||
|
if ((privateKey == null) || (publicValue == null)) {
|
||||||
|
throw new IllegalStateException("Not initialized correctly");
|
||||||
|
}
|
||||||
|
long keyType = CKK_GENERIC_SECRET;
|
||||||
|
Session session = null;
|
||||||
|
long privKeyID = privateKey.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
|
||||||
|
};
|
||||||
|
CK_ECDH1_DERIVE_PARAMS ckParams =
|
||||||
|
new CK_ECDH1_DERIVE_PARAMS(CKD_NULL, null, publicValue);
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
||||||
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism, ckParams), privKeyID,
|
||||||
|
attributes);
|
||||||
|
CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE_LEN),
|
||||||
|
};
|
||||||
|
token.p11.C_GetAttributeValue(session.id(), keyID, lenAttributes);
|
||||||
|
int keyLen = (int)lenAttributes[0].getLong();
|
||||||
|
SecretKey key = P11Key.secretKey
|
||||||
|
(session, keyID, algorithm, keyLen << 3, attributes);
|
||||||
|
return key;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not derive key", e);
|
||||||
|
} finally {
|
||||||
|
privateKey.releaseKeyID();
|
||||||
|
publicValue = null;
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
339
src/main/java/com/sunyard/security/pkcs11/P11ECKeyFactory.java
Normal file
339
src/main/java/com/sunyard/security/pkcs11/P11ECKeyFactory.java
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
import sun.security.util.DerValue;
|
||||||
|
import sun.security.util.ECUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EC KeyFactory implementation.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
final class P11ECKeyFactory extends P11KeyFactory {
|
||||||
|
private static Provider sunECprovider;
|
||||||
|
|
||||||
|
private static Provider getSunECProvider() {
|
||||||
|
if (sunECprovider == null) {
|
||||||
|
sunECprovider = Security.getProvider("SunEC");
|
||||||
|
if (sunECprovider == null) {
|
||||||
|
throw new RuntimeException("Cannot load SunEC provider");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sunECprovider;
|
||||||
|
}
|
||||||
|
|
||||||
|
P11ECKeyFactory(Token token, String algorithm) {
|
||||||
|
super(token, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ECParameterSpec getECParameterSpec(String name) {
|
||||||
|
return ECUtil.getECParameterSpec(getSunECProvider(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ECParameterSpec getECParameterSpec(int keySize) {
|
||||||
|
return ECUtil.getECParameterSpec(getSunECProvider(), keySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that spec is a known supported curve and convert it to our
|
||||||
|
// ECParameterSpec subclass. If not possible, return null.
|
||||||
|
static ECParameterSpec getECParameterSpec(ECParameterSpec spec) {
|
||||||
|
return ECUtil.getECParameterSpec(getSunECProvider(), spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ECParameterSpec decodeParameters(byte[] params) throws IOException {
|
||||||
|
return ECUtil.getECParameterSpec(getSunECProvider(), params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] encodeParameters(ECParameterSpec params) {
|
||||||
|
return ECUtil.encodeECParameterSpec(getSunECProvider(), params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ECPoint decodePoint(byte[] encoded, EllipticCurve curve) throws IOException {
|
||||||
|
return ECUtil.decodePoint(encoded, curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used by ECDH KeyAgreement
|
||||||
|
static byte[] getEncodedPublicValue(PublicKey key) throws InvalidKeyException {
|
||||||
|
if (key instanceof ECPublicKey) {
|
||||||
|
ECPublicKey ecKey = (ECPublicKey)key;
|
||||||
|
ECPoint w = ecKey.getW();
|
||||||
|
ECParameterSpec params = ecKey.getParams();
|
||||||
|
return ECUtil.encodePoint(w, params.getCurve());
|
||||||
|
} else {
|
||||||
|
// should never occur
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key class not yet supported: " + key.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
if (key instanceof ECPublicKey) {
|
||||||
|
ECPublicKey ecKey = (ECPublicKey)key;
|
||||||
|
return generatePublic(
|
||||||
|
ecKey.getW(),
|
||||||
|
ecKey.getParams()
|
||||||
|
);
|
||||||
|
} else if ("X.509".equals(key.getFormat())) {
|
||||||
|
// let Sun provider parse for us, then recurse
|
||||||
|
byte[] encoded = key.getEncoded();
|
||||||
|
|
||||||
|
try {
|
||||||
|
key = P11ECUtil.decodeX509ECPublicKey(encoded);
|
||||||
|
} catch (InvalidKeySpecException ikse) {
|
||||||
|
throw new InvalidKeyException(ikse);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implTranslatePublicKey(key);
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("PublicKey must be instance "
|
||||||
|
+ "of ECPublicKey or have X.509 encoding");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create EC public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateKey implTranslatePrivateKey(PrivateKey key)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
if (key instanceof ECPrivateKey) {
|
||||||
|
ECPrivateKey ecKey = (ECPrivateKey)key;
|
||||||
|
return generatePrivate(
|
||||||
|
ecKey.getS(),
|
||||||
|
ecKey.getParams()
|
||||||
|
);
|
||||||
|
} else if ("PKCS#8".equals(key.getFormat())) {
|
||||||
|
// let Sun provider parse for us, then recurse
|
||||||
|
byte[] encoded = key.getEncoded();
|
||||||
|
|
||||||
|
try {
|
||||||
|
key = P11ECUtil.decodePKCS8ECPrivateKey(encoded);
|
||||||
|
} catch (InvalidKeySpecException ikse) {
|
||||||
|
throw new InvalidKeyException(ikse);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implTranslatePrivateKey(key);
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("PrivateKey must be instance "
|
||||||
|
+ "of ECPrivateKey or have PKCS#8 encoding");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create EC private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected PublicKey engineGeneratePublic(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec instanceof X509EncodedKeySpec) {
|
||||||
|
try {
|
||||||
|
byte[] encoded = ((X509EncodedKeySpec)keySpec).getEncoded();
|
||||||
|
PublicKey key = P11ECUtil.decodeX509ECPublicKey(encoded);
|
||||||
|
return implTranslatePublicKey(key);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create EC public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keySpec instanceof ECPublicKeySpec == false) {
|
||||||
|
throw new InvalidKeySpecException("Only ECPublicKeySpec and "
|
||||||
|
+ "X509EncodedKeySpec supported for EC public keys");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ECPublicKeySpec ec = (ECPublicKeySpec)keySpec;
|
||||||
|
return generatePublic(
|
||||||
|
ec.getW(),
|
||||||
|
ec.getParams()
|
||||||
|
);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create EC public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||||
|
try {
|
||||||
|
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
|
||||||
|
PrivateKey key = P11ECUtil.decodePKCS8ECPrivateKey(encoded);
|
||||||
|
return implTranslatePrivateKey(key);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create EC private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keySpec instanceof ECPrivateKeySpec == false) {
|
||||||
|
throw new InvalidKeySpecException("Only ECPrivateKeySpec and "
|
||||||
|
+ "PKCS8EncodedKeySpec supported for EC private keys");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ECPrivateKeySpec ec = (ECPrivateKeySpec)keySpec;
|
||||||
|
return generatePrivate(
|
||||||
|
ec.getS(),
|
||||||
|
ec.getParams()
|
||||||
|
);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create EC private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicKey generatePublic(ECPoint point, ECParameterSpec params)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
byte[] encodedParams =
|
||||||
|
ECUtil.encodeECParameterSpec(getSunECProvider(), params);
|
||||||
|
byte[] encodedPoint =
|
||||||
|
ECUtil.encodePoint(point, params.getCurve());
|
||||||
|
|
||||||
|
// Check whether the X9.63 encoding of an EC point shall be wrapped
|
||||||
|
// in an ASN.1 OCTET STRING
|
||||||
|
if (!token.config.getUseEcX963Encoding()) {
|
||||||
|
try {
|
||||||
|
encodedPoint =
|
||||||
|
new DerValue(DerValue.tag_OctetString, encodedPoint)
|
||||||
|
.toByteArray();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new
|
||||||
|
IllegalArgumentException("Could not DER encode point", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_EC),
|
||||||
|
new CK_ATTRIBUTE(CKA_EC_POINT, encodedPoint),
|
||||||
|
new CK_ATTRIBUTE(CKA_EC_PARAMS, encodedParams),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PUBLIC_KEY, CKK_EC, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.publicKey
|
||||||
|
(session, keyID, "EC", params.getCurve().getField().getFieldSize(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PrivateKey generatePrivate(BigInteger s, ECParameterSpec params)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
byte[] encodedParams =
|
||||||
|
ECUtil.encodeECParameterSpec(getSunECProvider(), params);
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_EC),
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE, s),
|
||||||
|
new CK_ATTRIBUTE(CKA_EC_PARAMS, encodedParams),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PRIVATE_KEY, CKK_EC, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.privateKey
|
||||||
|
(session, keyID, "EC", params.getCurve().getField().getFieldSize(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException {
|
||||||
|
if (keySpec.isAssignableFrom(ECPublicKeySpec.class)) {
|
||||||
|
session[0] = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_EC_POINT),
|
||||||
|
new CK_ATTRIBUTE(CKA_EC_PARAMS),
|
||||||
|
};
|
||||||
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
|
||||||
|
ECPoint point = decodePoint(attributes[0].getByteArray(), params.getCurve());
|
||||||
|
return keySpec.cast(new ECPublicKeySpec(point, params));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidKeySpecException("Could not parse key", e);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
} else { // X.509 handled in superclass
|
||||||
|
throw new InvalidKeySpecException("Only ECPublicKeySpec and "
|
||||||
|
+ "X509EncodedKeySpec supported for EC public keys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException {
|
||||||
|
if (keySpec.isAssignableFrom(ECPrivateKeySpec.class)) {
|
||||||
|
session[0] = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE),
|
||||||
|
new CK_ATTRIBUTE(CKA_EC_PARAMS),
|
||||||
|
};
|
||||||
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
|
||||||
|
return keySpec.cast(
|
||||||
|
new ECPrivateKeySpec(attributes[0].getBigInteger(), params));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new InvalidKeySpecException("Could not parse key", e);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
} else { // PKCS#8 handled in superclass
|
||||||
|
throw new InvalidKeySpecException("Only ECPrivateKeySpec "
|
||||||
|
+ "and PKCS8EncodedKeySpec supported for EC private keys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
|
||||||
|
return KeyFactory.getInstance("EC", getSunECProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
114
src/main/java/com/sunyard/security/pkcs11/P11ECUtil.java
Normal file
114
src/main/java/com/sunyard/security/pkcs11/P11ECUtil.java
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import sun.security.ec.ECPublicKeyImpl;
|
||||||
|
import sun.security.ec.ECPrivateKeyImpl;
|
||||||
|
import sun.security.x509.X509Key;
|
||||||
|
|
||||||
|
final class P11ECUtil {
|
||||||
|
|
||||||
|
static ECPublicKey decodeX509ECPublicKey(byte[] encoded)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
|
||||||
|
|
||||||
|
return (ECPublicKey)ECGeneratePublic(keySpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] x509EncodeECPublicKey(ECPoint w,
|
||||||
|
ECParameterSpec params) throws InvalidKeySpecException {
|
||||||
|
ECPublicKeySpec keySpec = new ECPublicKeySpec(w, params);
|
||||||
|
X509Key key = (X509Key)ECGeneratePublic(keySpec);
|
||||||
|
|
||||||
|
return key.getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ECPrivateKey decodePKCS8ECPrivateKey(byte[] encoded)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
|
||||||
|
|
||||||
|
return (ECPrivateKey)ECGeneratePrivate(keySpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ECPrivateKey generateECPrivateKey(BigInteger s,
|
||||||
|
ECParameterSpec params) throws InvalidKeySpecException {
|
||||||
|
ECPrivateKeySpec keySpec = new ECPrivateKeySpec(s, params);
|
||||||
|
|
||||||
|
return (ECPrivateKey)ECGeneratePrivate(keySpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PublicKey ECGeneratePublic(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
try {
|
||||||
|
if (keySpec instanceof X509EncodedKeySpec) {
|
||||||
|
X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec;
|
||||||
|
return new ECPublicKeyImpl(x509Spec.getEncoded());
|
||||||
|
} else if (keySpec instanceof ECPublicKeySpec) {
|
||||||
|
ECPublicKeySpec ecSpec = (ECPublicKeySpec)keySpec;
|
||||||
|
return new ECPublicKeyImpl(
|
||||||
|
ecSpec.getW(),
|
||||||
|
ecSpec.getParams()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeySpecException("Only ECPublicKeySpec "
|
||||||
|
+ "and X509EncodedKeySpec supported for EC public keys");
|
||||||
|
}
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeySpecException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PrivateKey ECGeneratePrivate(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
try {
|
||||||
|
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||||
|
PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;
|
||||||
|
return new ECPrivateKeyImpl(pkcsSpec.getEncoded());
|
||||||
|
} else if (keySpec instanceof ECPrivateKeySpec) {
|
||||||
|
ECPrivateKeySpec ecSpec = (ECPrivateKeySpec)keySpec;
|
||||||
|
return new ECPrivateKeyImpl(ecSpec.getS(), ecSpec.getParams());
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeySpecException("Only ECPrivateKeySpec "
|
||||||
|
+ "and PKCS8EncodedKeySpec supported for EC private keys");
|
||||||
|
}
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeySpecException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private P11ECUtil() {}
|
||||||
|
|
||||||
|
}
|
1408
src/main/java/com/sunyard/security/pkcs11/P11Key.java
Normal file
1408
src/main/java/com/sunyard/security/pkcs11/P11Key.java
Normal file
File diff suppressed because it is too large
Load Diff
372
src/main/java/com/sunyard/security/pkcs11/P11KeyAgreement.java
Normal file
372
src/main/java/com/sunyard/security/pkcs11/P11KeyAgreement.java
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.interfaces.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
import sun.security.util.KeyUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyAgreement implementation class. This class currently supports
|
||||||
|
* DH.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11KeyAgreement extends KeyAgreementSpi {
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private final long mechanism;
|
||||||
|
|
||||||
|
// private key, if initialized
|
||||||
|
private P11Key privateKey;
|
||||||
|
|
||||||
|
// other sides public value ("y"), if doPhase() already called
|
||||||
|
private BigInteger publicValue;
|
||||||
|
|
||||||
|
// length of the secret to be derived
|
||||||
|
private int secretLen;
|
||||||
|
|
||||||
|
// KeyAgreement from SunJCE as fallback for > 2 party agreement
|
||||||
|
private KeyAgreement multiPartyAgreement;
|
||||||
|
|
||||||
|
private static class AllowKDF {
|
||||||
|
|
||||||
|
private static final boolean VALUE = getValue();
|
||||||
|
|
||||||
|
private static boolean getValue() {
|
||||||
|
return AccessController.doPrivileged(
|
||||||
|
(PrivilegedAction<Boolean>)
|
||||||
|
() -> Boolean.getBoolean("jdk.crypto.KeyAgreement.legacyKDF"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
P11KeyAgreement(Token token, String algorithm, long mechanism) {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(Key key, SecureRandom random)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
if (key instanceof PrivateKey == false) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key must be instance of PrivateKey");
|
||||||
|
}
|
||||||
|
privateKey = P11KeyFactory.convertKey(token, key, algorithm);
|
||||||
|
publicValue = null;
|
||||||
|
multiPartyAgreement = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(Key key, AlgorithmParameterSpec params,
|
||||||
|
SecureRandom random) throws InvalidKeyException,
|
||||||
|
InvalidAlgorithmParameterException {
|
||||||
|
if (params != null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Parameters not supported");
|
||||||
|
}
|
||||||
|
engineInit(key, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected Key engineDoPhase(Key key, boolean lastPhase)
|
||||||
|
throws InvalidKeyException, IllegalStateException {
|
||||||
|
if (privateKey == null) {
|
||||||
|
throw new IllegalStateException("Not initialized");
|
||||||
|
}
|
||||||
|
if (publicValue != null) {
|
||||||
|
throw new IllegalStateException("Phase already executed");
|
||||||
|
}
|
||||||
|
// PKCS#11 only allows key agreement between 2 parties
|
||||||
|
// JCE allows >= 2 parties. To support that case (for compatibility
|
||||||
|
// and to pass JCK), fall back to SunJCE in this case.
|
||||||
|
// NOTE that we initialize using the P11Key, which will fail if it
|
||||||
|
// is sensitive/unextractable. However, this is not an issue in the
|
||||||
|
// compatibility configuration, which is all we are targeting here.
|
||||||
|
if ((multiPartyAgreement != null) || (lastPhase == false)) {
|
||||||
|
if (multiPartyAgreement == null) {
|
||||||
|
try {
|
||||||
|
multiPartyAgreement = KeyAgreement.getInstance
|
||||||
|
("DH", P11Util.getSunJceProvider());
|
||||||
|
multiPartyAgreement.init(privateKey);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Could not initialize multi party agreement", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return multiPartyAgreement.doPhase(key, lastPhase);
|
||||||
|
}
|
||||||
|
if ((key instanceof PublicKey == false)
|
||||||
|
|| (key.getAlgorithm().equals(algorithm) == false)) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key must be a PublicKey with algorithm DH");
|
||||||
|
}
|
||||||
|
BigInteger p, g, y;
|
||||||
|
if (key instanceof DHPublicKey) {
|
||||||
|
DHPublicKey dhKey = (DHPublicKey)key;
|
||||||
|
|
||||||
|
// validate the Diffie-Hellman public key
|
||||||
|
KeyUtil.validate(dhKey);
|
||||||
|
|
||||||
|
y = dhKey.getY();
|
||||||
|
DHParameterSpec params = dhKey.getParams();
|
||||||
|
p = params.getP();
|
||||||
|
g = params.getG();
|
||||||
|
} else {
|
||||||
|
// normally, DH PublicKeys will always implement DHPublicKey
|
||||||
|
// just in case not, attempt conversion
|
||||||
|
P11DHKeyFactory kf = new P11DHKeyFactory(token, "DH");
|
||||||
|
try {
|
||||||
|
DHPublicKeySpec spec = kf.engineGetKeySpec(
|
||||||
|
key, DHPublicKeySpec.class);
|
||||||
|
|
||||||
|
// validate the Diffie-Hellman public key
|
||||||
|
KeyUtil.validate(spec);
|
||||||
|
|
||||||
|
y = spec.getY();
|
||||||
|
p = spec.getP();
|
||||||
|
g = spec.getG();
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw new InvalidKeyException("Could not obtain key values", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if parameters of private key are accessible, verify that
|
||||||
|
// they match parameters of public key
|
||||||
|
// XXX p and g should always be readable, even if the key is sensitive
|
||||||
|
if (privateKey instanceof DHPrivateKey) {
|
||||||
|
DHPrivateKey dhKey = (DHPrivateKey)privateKey;
|
||||||
|
DHParameterSpec params = dhKey.getParams();
|
||||||
|
if ((p.equals(params.getP()) == false)
|
||||||
|
|| (g.equals(params.getG()) == false)) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("PublicKey DH parameters must match PrivateKey DH parameters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
publicValue = y;
|
||||||
|
// length of the secret is length of key
|
||||||
|
secretLen = (p.bitLength() + 7) >> 3;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineGenerateSecret() throws IllegalStateException {
|
||||||
|
if (multiPartyAgreement != null) {
|
||||||
|
byte[] val = multiPartyAgreement.generateSecret();
|
||||||
|
multiPartyAgreement = null;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
if ((privateKey == null) || (publicValue == null)) {
|
||||||
|
throw new IllegalStateException("Not initialized correctly");
|
||||||
|
}
|
||||||
|
Session session = null;
|
||||||
|
long privKeyID = privateKey.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
|
||||||
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism, publicValue), privKeyID,
|
||||||
|
attributes);
|
||||||
|
|
||||||
|
attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE)
|
||||||
|
};
|
||||||
|
token.p11.C_GetAttributeValue(session.id(), keyID, attributes);
|
||||||
|
byte[] secret = attributes[0].getByteArray();
|
||||||
|
token.p11.C_DestroyObject(session.id(), keyID);
|
||||||
|
// Some vendors, e.g. NSS, trim off the leading 0x00 byte(s) from
|
||||||
|
// the generated secret. Thus, we need to check the secret length
|
||||||
|
// and trim/pad it so the returned value has the same length as
|
||||||
|
// the modulus size
|
||||||
|
if (secret.length == secretLen) {
|
||||||
|
return secret;
|
||||||
|
} else {
|
||||||
|
if (secret.length > secretLen) {
|
||||||
|
// Shouldn't happen; but check just in case
|
||||||
|
throw new ProviderException("generated secret is out-of-range");
|
||||||
|
}
|
||||||
|
byte[] newSecret = new byte[secretLen];
|
||||||
|
System.arraycopy(secret, 0, newSecret, secretLen - secret.length,
|
||||||
|
secret.length);
|
||||||
|
return newSecret;
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Could not derive key", e);
|
||||||
|
} finally {
|
||||||
|
privateKey.releaseKeyID();
|
||||||
|
publicValue = null;
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineGenerateSecret(byte[] sharedSecret, int
|
||||||
|
offset) throws IllegalStateException, ShortBufferException {
|
||||||
|
if (multiPartyAgreement != null) {
|
||||||
|
int n = multiPartyAgreement.generateSecret(sharedSecret, offset);
|
||||||
|
multiPartyAgreement = null;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
if (offset + secretLen > sharedSecret.length) {
|
||||||
|
throw new ShortBufferException("Need " + secretLen
|
||||||
|
+ " bytes, only " + (sharedSecret.length - offset) + " available");
|
||||||
|
}
|
||||||
|
byte[] secret = engineGenerateSecret();
|
||||||
|
System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
|
||||||
|
return secret.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected SecretKey engineGenerateSecret(String algorithm)
|
||||||
|
throws IllegalStateException, NoSuchAlgorithmException,
|
||||||
|
InvalidKeyException {
|
||||||
|
if (multiPartyAgreement != null) {
|
||||||
|
SecretKey key = multiPartyAgreement.generateSecret(algorithm);
|
||||||
|
multiPartyAgreement = null;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
if (algorithm == null) {
|
||||||
|
throw new NoSuchAlgorithmException("Algorithm must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (algorithm.equals("TlsPremasterSecret")) {
|
||||||
|
// For now, only perform native derivation for TlsPremasterSecret
|
||||||
|
// as that is required for FIPS compliance.
|
||||||
|
// For other algorithms, there are unresolved issues regarding
|
||||||
|
// how this should work in JCE plus a Solaris truncation bug.
|
||||||
|
// (bug not yet filed).
|
||||||
|
return nativeGenerateSecret(algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!algorithm.equalsIgnoreCase("TlsPremasterSecret") &&
|
||||||
|
!AllowKDF.VALUE) {
|
||||||
|
|
||||||
|
throw new NoSuchAlgorithmException("Unsupported secret key "
|
||||||
|
+ "algorithm: " + algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] secret = engineGenerateSecret();
|
||||||
|
// Maintain compatibility for SunJCE:
|
||||||
|
// verify secret length is sensible for algorithm / truncate
|
||||||
|
// return generated key itself if possible
|
||||||
|
int keyLen;
|
||||||
|
if (algorithm.equalsIgnoreCase("DES")) {
|
||||||
|
keyLen = 8;
|
||||||
|
} else if (algorithm.equalsIgnoreCase("DESede")) {
|
||||||
|
keyLen = 24;
|
||||||
|
} else if (algorithm.equalsIgnoreCase("Blowfish")) {
|
||||||
|
keyLen = Math.min(56, secret.length);
|
||||||
|
} else if (algorithm.equalsIgnoreCase("TlsPremasterSecret")) {
|
||||||
|
keyLen = secret.length;
|
||||||
|
} else {
|
||||||
|
throw new NoSuchAlgorithmException
|
||||||
|
("Unknown algorithm " + algorithm);
|
||||||
|
}
|
||||||
|
if (secret.length < keyLen) {
|
||||||
|
throw new InvalidKeyException("Secret too short");
|
||||||
|
}
|
||||||
|
if (algorithm.equalsIgnoreCase("DES") ||
|
||||||
|
algorithm.equalsIgnoreCase("DESede")) {
|
||||||
|
for (int i = 0; i < keyLen; i+=8) {
|
||||||
|
P11SecretKeyFactory.fixDESParity(secret, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new SecretKeySpec(secret, 0, keyLen, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecretKey nativeGenerateSecret(String algorithm)
|
||||||
|
throws IllegalStateException, NoSuchAlgorithmException,
|
||||||
|
InvalidKeyException {
|
||||||
|
if ((privateKey == null) || (publicValue == null)) {
|
||||||
|
throw new IllegalStateException("Not initialized correctly");
|
||||||
|
}
|
||||||
|
long keyType = CKK_GENERIC_SECRET;
|
||||||
|
Session session = null;
|
||||||
|
long privKeyID = privateKey.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
||||||
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism, publicValue), privKeyID,
|
||||||
|
attributes);
|
||||||
|
CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE_LEN),
|
||||||
|
};
|
||||||
|
token.p11.C_GetAttributeValue(session.id(), keyID, lenAttributes);
|
||||||
|
int keyLen = (int)lenAttributes[0].getLong();
|
||||||
|
SecretKey key = P11Key.secretKey
|
||||||
|
(session, keyID, algorithm, keyLen << 3, attributes);
|
||||||
|
if ("RAW".equals(key.getFormat())) {
|
||||||
|
// Workaround for Solaris bug 6318543.
|
||||||
|
// Strip leading zeroes ourselves if possible (key not sensitive).
|
||||||
|
// This should be removed once the Solaris fix is available
|
||||||
|
// as here we always retrieve the CKA_VALUE even for tokens
|
||||||
|
// that do not have that bug.
|
||||||
|
byte[] keyBytes = key.getEncoded();
|
||||||
|
byte[] newBytes = KeyUtil.trimZeroes(keyBytes);
|
||||||
|
if (keyBytes != newBytes) {
|
||||||
|
key = new SecretKeySpec(newBytes, algorithm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not derive key", e);
|
||||||
|
} finally {
|
||||||
|
privateKey.releaseKeyID();
|
||||||
|
publicValue = null;
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
154
src/main/java/com/sunyard/security/pkcs11/P11KeyFactory.java
Normal file
154
src/main/java/com/sunyard/security/pkcs11/P11KeyFactory.java
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.PKCS11Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyFactory base class. Provides common infrastructure for the RSA, DSA,
|
||||||
|
* and DH implementations.
|
||||||
|
*
|
||||||
|
* The subclasses support conversion between keys and keyspecs
|
||||||
|
* using X.509, PKCS#8, and their individual algorithm specific formats,
|
||||||
|
* assuming keys are extractable.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
abstract class P11KeyFactory extends KeyFactorySpi {
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
final Token token;
|
||||||
|
|
||||||
|
// algorithm name, currently one of RSA, DSA, DH
|
||||||
|
final String algorithm;
|
||||||
|
|
||||||
|
P11KeyFactory(Token token, String algorithm) {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an arbitrary key of algorithm into a P11Key of token.
|
||||||
|
* Used by P11Signature.init() and RSACipher.init().
|
||||||
|
*/
|
||||||
|
static P11Key convertKey(Token token, Key key, String algorithm)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
return (P11Key)token.getKeyFactory(algorithm).engineTranslateKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected final <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if ((key == null) || (keySpec == null)) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("key and keySpec must not be null");
|
||||||
|
}
|
||||||
|
// delegate to our Java based providers for PKCS#8 and X.509
|
||||||
|
if (keySpec.isAssignableFrom(PKCS8EncodedKeySpec.class)
|
||||||
|
|| keySpec.isAssignableFrom(X509EncodedKeySpec.class)) {
|
||||||
|
try {
|
||||||
|
return implGetSoftwareFactory().getKeySpec(key, keySpec);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeySpecException("Could not encode key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// first translate into a key of this token, if it is not already
|
||||||
|
P11Key p11Key;
|
||||||
|
try {
|
||||||
|
p11Key = (P11Key)engineTranslateKey(key);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException("Could not convert key", e);
|
||||||
|
}
|
||||||
|
Session[] session = new Session[1];
|
||||||
|
try {
|
||||||
|
if (p11Key.isPublic()) {
|
||||||
|
return implGetPublicKeySpec(p11Key, keySpec, session);
|
||||||
|
} else {
|
||||||
|
return implGetPrivateKeySpec(p11Key, keySpec, session);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeySpecException("Could not generate KeySpec", e);
|
||||||
|
} finally {
|
||||||
|
session[0] = token.releaseSession(session[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected final Key engineTranslateKey(Key key) throws InvalidKeyException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (key == null) {
|
||||||
|
throw new InvalidKeyException("Key must not be null");
|
||||||
|
}
|
||||||
|
if (key.getAlgorithm().equals(this.algorithm) == false) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key algorithm must be " + algorithm);
|
||||||
|
}
|
||||||
|
if (key instanceof P11Key) {
|
||||||
|
P11Key p11Key = (P11Key)key;
|
||||||
|
if (p11Key.token == token) {
|
||||||
|
// already a key of this token, no need to translate
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
P11Key p11Key = token.privateCache.get(key);
|
||||||
|
if (p11Key != null) {
|
||||||
|
return p11Key;
|
||||||
|
}
|
||||||
|
if (key instanceof PublicKey) {
|
||||||
|
PublicKey publicKey = implTranslatePublicKey((PublicKey)key);
|
||||||
|
token.privateCache.put(key, (P11Key)publicKey);
|
||||||
|
return publicKey;
|
||||||
|
} else if (key instanceof PrivateKey) {
|
||||||
|
PrivateKey privateKey = implTranslatePrivateKey((PrivateKey)key);
|
||||||
|
token.privateCache.put(key, (P11Key)privateKey);
|
||||||
|
return privateKey;
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key must be instance of PublicKey or PrivateKey");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract <T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException;
|
||||||
|
|
||||||
|
abstract <T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException;
|
||||||
|
|
||||||
|
abstract PublicKey implTranslatePublicKey(PublicKey key)
|
||||||
|
throws InvalidKeyException;
|
||||||
|
|
||||||
|
abstract PrivateKey implTranslatePrivateKey(PrivateKey key)
|
||||||
|
throws InvalidKeyException;
|
||||||
|
|
||||||
|
abstract KeyFactory implGetSoftwareFactory() throws GeneralSecurityException;
|
||||||
|
|
||||||
|
}
|
286
src/main/java/com/sunyard/security/pkcs11/P11KeyGenerator.java
Normal file
286
src/main/java/com/sunyard/security/pkcs11/P11KeyGenerator.java
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyGenerator implementation class. This class currently supports
|
||||||
|
* DES, DESede, AES, ARCFOUR, and Blowfish.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11KeyGenerator extends KeyGeneratorSpi {
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private long mechanism;
|
||||||
|
|
||||||
|
// raw key size in bits, e.g. 64 for DES. Always valid.
|
||||||
|
private int keySize;
|
||||||
|
|
||||||
|
// bits of entropy in the key, e.g. 56 for DES. Always valid.
|
||||||
|
private int significantKeySize;
|
||||||
|
|
||||||
|
// keyType (CKK_*), needed for TemplateManager call only.
|
||||||
|
private long keyType;
|
||||||
|
|
||||||
|
// for determining if both 112 and 168 bits of DESede key lengths
|
||||||
|
// are supported.
|
||||||
|
private boolean supportBothKeySizes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method for checking if the specified key size is valid
|
||||||
|
* and within the supported range. Return the significant key size
|
||||||
|
* upon successful validation.
|
||||||
|
* @param keyGenMech the PKCS#11 key generation mechanism.
|
||||||
|
* @param keySize the to-be-checked key size for this mechanism.
|
||||||
|
* @param token token which provides this mechanism.
|
||||||
|
* @return the significant key size (in bits) corresponding to the
|
||||||
|
* specified key size.
|
||||||
|
* @throws InvalidParameterException if the specified key size is invalid.
|
||||||
|
* @throws ProviderException if this mechanism isn't supported by SunPKCS11
|
||||||
|
* or underlying native impl.
|
||||||
|
*/
|
||||||
|
static int checkKeySize(long keyGenMech, int keySize, Token token)
|
||||||
|
throws InvalidAlgorithmParameterException, ProviderException {
|
||||||
|
int sigKeySize;
|
||||||
|
switch ((int)keyGenMech) {
|
||||||
|
case (int)CKM_DES_KEY_GEN:
|
||||||
|
if ((keySize != 64) && (keySize != 56)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("DES key length must be 56 bits");
|
||||||
|
}
|
||||||
|
sigKeySize = 56;
|
||||||
|
break;
|
||||||
|
case (int)CKM_DES2_KEY_GEN:
|
||||||
|
case (int)CKM_DES3_KEY_GEN:
|
||||||
|
if ((keySize == 112) || (keySize == 128)) {
|
||||||
|
sigKeySize = 112;
|
||||||
|
} else if ((keySize == 168) || (keySize == 192)) {
|
||||||
|
sigKeySize = 168;
|
||||||
|
} else {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("DESede key length must be 112, or 168 bits");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Handle all variable-key-length algorithms here
|
||||||
|
CK_MECHANISM_INFO info = null;
|
||||||
|
try {
|
||||||
|
info = token.getMechanismInfo(keyGenMech);
|
||||||
|
} catch (PKCS11Exception p11e) {
|
||||||
|
// Should never happen
|
||||||
|
throw new ProviderException
|
||||||
|
("Cannot retrieve mechanism info", p11e);
|
||||||
|
}
|
||||||
|
if (info == null) {
|
||||||
|
// XXX Unable to retrieve the supported key length from
|
||||||
|
// the underlying native impl. Skip the checking for now.
|
||||||
|
return keySize;
|
||||||
|
}
|
||||||
|
// PKCS#11 defines these to be in number of bytes except for
|
||||||
|
// RC4 which is in bits. However, some PKCS#11 impls still use
|
||||||
|
// bytes for all mechs, e.g. NSS. We try to detect this
|
||||||
|
// inconsistency if the minKeySize seems unreasonably small.
|
||||||
|
int minKeySize = info.iMinKeySize;
|
||||||
|
int maxKeySize = info.iMaxKeySize;
|
||||||
|
if (keyGenMech != CKM_RC4_KEY_GEN || minKeySize < 8) {
|
||||||
|
minKeySize = Math.multiplyExact(minKeySize, 8);
|
||||||
|
if (maxKeySize != Integer.MAX_VALUE) {
|
||||||
|
maxKeySize = Math.multiplyExact(maxKeySize, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Explicitly disallow keys shorter than 40-bits for security
|
||||||
|
if (minKeySize < 40) minKeySize = 40;
|
||||||
|
if (keySize < minKeySize || keySize > maxKeySize) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Key length must be between " + minKeySize +
|
||||||
|
" and " + maxKeySize + " bits");
|
||||||
|
}
|
||||||
|
if (keyGenMech == CKM_AES_KEY_GEN) {
|
||||||
|
if ((keySize != 128) && (keySize != 192) &&
|
||||||
|
(keySize != 256)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("AES key length must be " + minKeySize +
|
||||||
|
(maxKeySize >= 192? ", 192":"") +
|
||||||
|
(maxKeySize >= 256? ", or 256":"") + " bits");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sigKeySize = keySize;
|
||||||
|
}
|
||||||
|
return sigKeySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
P11KeyGenerator(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
|
||||||
|
if (this.mechanism == CKM_DES3_KEY_GEN) {
|
||||||
|
/* Given the current lookup order specified in SunPKCS11.java,
|
||||||
|
if CKM_DES2_KEY_GEN is used to construct this object, it
|
||||||
|
means that CKM_DES3_KEY_GEN is disabled or unsupported.
|
||||||
|
*/
|
||||||
|
supportBothKeySizes =
|
||||||
|
(token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
|
||||||
|
(token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));
|
||||||
|
}
|
||||||
|
setDefaultKeySize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set default keysize and also initialize keyType
|
||||||
|
private void setDefaultKeySize() {
|
||||||
|
switch ((int)mechanism) {
|
||||||
|
case (int)CKM_DES_KEY_GEN:
|
||||||
|
keySize = 64;
|
||||||
|
keyType = CKK_DES;
|
||||||
|
break;
|
||||||
|
case (int)CKM_DES2_KEY_GEN:
|
||||||
|
keySize = 128;
|
||||||
|
keyType = CKK_DES2;
|
||||||
|
break;
|
||||||
|
case (int)CKM_DES3_KEY_GEN:
|
||||||
|
keySize = 192;
|
||||||
|
keyType = CKK_DES3;
|
||||||
|
break;
|
||||||
|
case (int)CKM_AES_KEY_GEN:
|
||||||
|
keySize = 128;
|
||||||
|
keyType = CKK_AES;
|
||||||
|
break;
|
||||||
|
case (int)CKM_RC4_KEY_GEN:
|
||||||
|
keySize = 128;
|
||||||
|
keyType = CKK_RC4;
|
||||||
|
break;
|
||||||
|
case (int)CKM_BLOWFISH_KEY_GEN:
|
||||||
|
keySize = 128;
|
||||||
|
keyType = CKK_BLOWFISH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unknown mechanism " + mechanism);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
significantKeySize = checkKeySize(mechanism, keySize, token);
|
||||||
|
} catch (InvalidAlgorithmParameterException iape) {
|
||||||
|
throw new ProviderException("Unsupported default key size", iape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(SecureRandom random) {
|
||||||
|
token.ensureValid();
|
||||||
|
setDefaultKeySize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(AlgorithmParameterSpec params,
|
||||||
|
SecureRandom random) throws InvalidAlgorithmParameterException {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("AlgorithmParameterSpec not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(int keySize, SecureRandom random) {
|
||||||
|
token.ensureValid();
|
||||||
|
int newSignificantKeySize;
|
||||||
|
try {
|
||||||
|
newSignificantKeySize = checkKeySize(mechanism, keySize, token);
|
||||||
|
} catch (InvalidAlgorithmParameterException iape) {
|
||||||
|
throw (InvalidParameterException)
|
||||||
|
(new InvalidParameterException().initCause(iape));
|
||||||
|
}
|
||||||
|
if ((mechanism == CKM_DES2_KEY_GEN) ||
|
||||||
|
(mechanism == CKM_DES3_KEY_GEN)) {
|
||||||
|
long newMechanism = (newSignificantKeySize == 112 ?
|
||||||
|
CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN);
|
||||||
|
if (mechanism != newMechanism) {
|
||||||
|
if (supportBothKeySizes) {
|
||||||
|
mechanism = newMechanism;
|
||||||
|
// Adjust keyType to reflect the mechanism change
|
||||||
|
keyType = (mechanism == CKM_DES2_KEY_GEN ?
|
||||||
|
CKK_DES2 : CKK_DES3);
|
||||||
|
} else {
|
||||||
|
throw new InvalidParameterException
|
||||||
|
("Only " + significantKeySize +
|
||||||
|
"-bit DESede is supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.keySize = keySize;
|
||||||
|
this.significantKeySize = newSignificantKeySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected SecretKey engineGenerateKey() {
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes;
|
||||||
|
switch ((int)keyType) {
|
||||||
|
case (int)CKK_DES:
|
||||||
|
case (int)CKK_DES2:
|
||||||
|
case (int)CKK_DES3:
|
||||||
|
// fixed length, do not specify CKA_VALUE_LEN
|
||||||
|
attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE_LEN, keySize >> 3),
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
||||||
|
long keyID = token.p11.C_GenerateKey
|
||||||
|
(session.id(), new CK_MECHANISM(mechanism), attributes);
|
||||||
|
return P11Key.secretKey
|
||||||
|
(session, keyID, algorithm, significantKeySize, attributes);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Could not generate key", e);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,427 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import javax.crypto.spec.DHParameterSpec;
|
||||||
|
|
||||||
|
import sun.security.provider.ParameterCache;
|
||||||
|
import static sun.security.util.SecurityProviderConstants.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
|
||||||
|
import sun.security.rsa.RSAKeyFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyPairGenerator implementation class. This class currently supports
|
||||||
|
* RSA, DSA, DH, and EC.
|
||||||
|
*
|
||||||
|
* Note that for DSA and DH we rely on the Sun and SunJCE providers to
|
||||||
|
* obtain the parameters from.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private final long mechanism;
|
||||||
|
|
||||||
|
// selected or default key size, always valid
|
||||||
|
private int keySize;
|
||||||
|
|
||||||
|
// parameters specified via init, if any
|
||||||
|
private AlgorithmParameterSpec params;
|
||||||
|
|
||||||
|
// for RSA, selected or default value of public exponent, always valid
|
||||||
|
private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
|
||||||
|
|
||||||
|
// the supported keysize range of the native PKCS11 library
|
||||||
|
// if mechanism info is unavailable, 0/Integer.MAX_VALUE is used
|
||||||
|
private final int minKeySize;
|
||||||
|
private final int maxKeySize;
|
||||||
|
|
||||||
|
// SecureRandom instance, if specified in init
|
||||||
|
private SecureRandom random;
|
||||||
|
|
||||||
|
P11KeyPairGenerator(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
super();
|
||||||
|
int minKeyLen = 0;
|
||||||
|
int maxKeyLen = Integer.MAX_VALUE;
|
||||||
|
try {
|
||||||
|
CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(mechanism);
|
||||||
|
if (mechInfo != null) {
|
||||||
|
minKeyLen = mechInfo.iMinKeySize;
|
||||||
|
maxKeyLen = mechInfo.iMaxKeySize;
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception p11e) {
|
||||||
|
// Should never happen
|
||||||
|
throw new ProviderException
|
||||||
|
("Unexpected error while getting mechanism info", p11e);
|
||||||
|
}
|
||||||
|
// set default key sizes and apply our own algorithm-specific limits
|
||||||
|
// override lower limit to disallow unsecure keys being generated
|
||||||
|
// override upper limit to deter DOS attack
|
||||||
|
if (algorithm.equals("EC")) {
|
||||||
|
keySize = DEF_EC_KEY_SIZE;
|
||||||
|
if (minKeyLen < 112) {
|
||||||
|
minKeyLen = 112;
|
||||||
|
}
|
||||||
|
if (maxKeyLen > 2048) {
|
||||||
|
maxKeyLen = 2048;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (algorithm.equals("DSA")) {
|
||||||
|
keySize = DEF_DSA_KEY_SIZE;
|
||||||
|
} else if (algorithm.equals("RSA")) {
|
||||||
|
keySize = DEF_RSA_KEY_SIZE;
|
||||||
|
if (maxKeyLen > 64 * 1024) {
|
||||||
|
maxKeyLen = 64 * 1024;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keySize = DEF_DH_KEY_SIZE;
|
||||||
|
}
|
||||||
|
if (minKeyLen < 512) {
|
||||||
|
minKeyLen = 512;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto-adjust default keysize in case it's out-of-range
|
||||||
|
if (keySize < minKeyLen) {
|
||||||
|
keySize = minKeyLen;
|
||||||
|
}
|
||||||
|
if (keySize > maxKeyLen) {
|
||||||
|
keySize = maxKeyLen;
|
||||||
|
}
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
this.minKeySize = minKeyLen;
|
||||||
|
this.maxKeySize = maxKeyLen;
|
||||||
|
initialize(keySize, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
public void initialize(int keySize, SecureRandom random) {
|
||||||
|
token.ensureValid();
|
||||||
|
try {
|
||||||
|
checkKeySize(keySize, null);
|
||||||
|
} catch (InvalidAlgorithmParameterException e) {
|
||||||
|
throw new InvalidParameterException(e.getMessage());
|
||||||
|
}
|
||||||
|
this.params = null;
|
||||||
|
if (algorithm.equals("EC")) {
|
||||||
|
params = P11ECKeyFactory.getECParameterSpec(keySize);
|
||||||
|
if (params == null) {
|
||||||
|
throw new InvalidParameterException(
|
||||||
|
"No EC parameters available for key size "
|
||||||
|
+ keySize + " bits");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.keySize = keySize;
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
|
||||||
|
throws InvalidAlgorithmParameterException {
|
||||||
|
token.ensureValid();
|
||||||
|
int tmpKeySize;
|
||||||
|
if (algorithm.equals("DH")) {
|
||||||
|
if (params instanceof DHParameterSpec == false) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("DHParameterSpec required for Diffie-Hellman");
|
||||||
|
}
|
||||||
|
DHParameterSpec dhParams = (DHParameterSpec) params;
|
||||||
|
tmpKeySize = dhParams.getP().bitLength();
|
||||||
|
checkKeySize(tmpKeySize, dhParams);
|
||||||
|
// XXX sanity check params
|
||||||
|
} else if (algorithm.equals("RSA")) {
|
||||||
|
if (params instanceof RSAKeyGenParameterSpec == false) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("RSAKeyGenParameterSpec required for RSA");
|
||||||
|
}
|
||||||
|
RSAKeyGenParameterSpec rsaParams =
|
||||||
|
(RSAKeyGenParameterSpec) params;
|
||||||
|
tmpKeySize = rsaParams.getKeysize();
|
||||||
|
checkKeySize(tmpKeySize, rsaParams);
|
||||||
|
// override the supplied params to null
|
||||||
|
params = null;
|
||||||
|
this.rsaPublicExponent = rsaParams.getPublicExponent();
|
||||||
|
// XXX sanity check params
|
||||||
|
} else if (algorithm.equals("DSA")) {
|
||||||
|
if (params instanceof DSAParameterSpec == false) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("DSAParameterSpec required for DSA");
|
||||||
|
}
|
||||||
|
DSAParameterSpec dsaParams = (DSAParameterSpec) params;
|
||||||
|
tmpKeySize = dsaParams.getP().bitLength();
|
||||||
|
checkKeySize(tmpKeySize, dsaParams);
|
||||||
|
// XXX sanity check params
|
||||||
|
} else if (algorithm.equals("EC")) {
|
||||||
|
ECParameterSpec ecParams;
|
||||||
|
if (params instanceof ECParameterSpec) {
|
||||||
|
ecParams = P11ECKeyFactory.getECParameterSpec(
|
||||||
|
(ECParameterSpec)params);
|
||||||
|
if (ecParams == null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Unsupported curve: " + params);
|
||||||
|
}
|
||||||
|
} else if (params instanceof ECGenParameterSpec) {
|
||||||
|
String name = ((ECGenParameterSpec) params).getName();
|
||||||
|
ecParams = P11ECKeyFactory.getECParameterSpec(name);
|
||||||
|
if (ecParams == null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Unknown curve name: " + name);
|
||||||
|
}
|
||||||
|
// override the supplied params with the derived one
|
||||||
|
params = ecParams;
|
||||||
|
} else {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("ECParameterSpec or ECGenParameterSpec required for EC");
|
||||||
|
}
|
||||||
|
tmpKeySize = ecParams.getCurve().getField().getFieldSize();
|
||||||
|
checkKeySize(tmpKeySize, ecParams);
|
||||||
|
} else {
|
||||||
|
throw new ProviderException("Unknown algorithm: " + algorithm);
|
||||||
|
}
|
||||||
|
this.keySize = tmpKeySize;
|
||||||
|
this.params = params;
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkKeySize(int keySize, AlgorithmParameterSpec params)
|
||||||
|
throws InvalidAlgorithmParameterException {
|
||||||
|
if (keySize <= 0) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("key size must be positive, got " + keySize);
|
||||||
|
}
|
||||||
|
// check native range first
|
||||||
|
if (keySize < minKeySize) {
|
||||||
|
throw new InvalidAlgorithmParameterException(algorithm +
|
||||||
|
" key must be at least " + minKeySize + " bits. " +
|
||||||
|
"The specific key size " + keySize + " is not supported");
|
||||||
|
}
|
||||||
|
if (keySize > maxKeySize) {
|
||||||
|
throw new InvalidAlgorithmParameterException(algorithm +
|
||||||
|
" key must be at most " + maxKeySize + " bits. " +
|
||||||
|
"The specific key size " + keySize + " is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check our own algorithm-specific limits also
|
||||||
|
if (algorithm.equals("EC")) {
|
||||||
|
if (keySize < 112) {
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"EC key size must be at least 112 bit. " +
|
||||||
|
"The specific key size " + keySize + " is not supported");
|
||||||
|
}
|
||||||
|
if (keySize > 2048) {
|
||||||
|
// sanity check, nobody really wants keys this large
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"EC key size must be at most 2048 bit. " +
|
||||||
|
"The specific key size " + keySize + " is not supported");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// RSA, DH, DSA
|
||||||
|
if (keySize < 512) {
|
||||||
|
throw new InvalidAlgorithmParameterException(algorithm +
|
||||||
|
" key size must be at least 512 bit. " +
|
||||||
|
"The specific key size " + keySize + " is not supported");
|
||||||
|
}
|
||||||
|
if (algorithm.equals("RSA")) {
|
||||||
|
BigInteger tmpExponent = rsaPublicExponent;
|
||||||
|
if (params != null) {
|
||||||
|
tmpExponent =
|
||||||
|
((RSAKeyGenParameterSpec)params).getPublicExponent();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
|
||||||
|
minKeySize, maxKeySize);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidAlgorithmParameterException(e);
|
||||||
|
}
|
||||||
|
} else if (algorithm.equals("DH")) {
|
||||||
|
if (params != null) { // initialized with specified parameters
|
||||||
|
// sanity check, nobody really wants keys this large
|
||||||
|
if (keySize > 64 * 1024) {
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"DH key size must be at most 65536 bit. " +
|
||||||
|
"The specific key size " +
|
||||||
|
keySize + " is not supported");
|
||||||
|
}
|
||||||
|
} else { // default parameters will be used.
|
||||||
|
// Range is based on the values in
|
||||||
|
// sun.security.provider.ParameterCache class.
|
||||||
|
if ((keySize > 8192) || (keySize < 512) ||
|
||||||
|
((keySize & 0x3f) != 0)) {
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"DH key size must be multiple of 64, and can " +
|
||||||
|
"only range from 512 to 8192 (inclusive). " +
|
||||||
|
"The specific key size " +
|
||||||
|
keySize + " is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
DHParameterSpec cache =
|
||||||
|
ParameterCache.getCachedDHParameterSpec(keySize);
|
||||||
|
// Except 2048 and 3072, not yet support generation of
|
||||||
|
// parameters bigger than 1024 bits.
|
||||||
|
if ((cache == null) && (keySize > 1024)) {
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"Unsupported " + keySize +
|
||||||
|
"-bit DH parameter generation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// this restriction is in the spec for DSA
|
||||||
|
if ((keySize != 3072) && (keySize != 2048) &&
|
||||||
|
((keySize > 1024) || ((keySize & 0x3f) != 0))) {
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"DSA key must be multiples of 64 if less than " +
|
||||||
|
"1024 bits, or 2048, 3072 bits. " +
|
||||||
|
"The specific key size " +
|
||||||
|
keySize + " is not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
public KeyPair generateKeyPair() {
|
||||||
|
token.ensureValid();
|
||||||
|
CK_ATTRIBUTE[] publicKeyTemplate;
|
||||||
|
CK_ATTRIBUTE[] privateKeyTemplate;
|
||||||
|
long keyType;
|
||||||
|
if (algorithm.equals("RSA")) {
|
||||||
|
keyType = CKK_RSA;
|
||||||
|
publicKeyTemplate = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_MODULUS_BITS, keySize),
|
||||||
|
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, rsaPublicExponent),
|
||||||
|
};
|
||||||
|
privateKeyTemplate = new CK_ATTRIBUTE[] {
|
||||||
|
// empty
|
||||||
|
};
|
||||||
|
} else if (algorithm.equals("DSA")) {
|
||||||
|
keyType = CKK_DSA;
|
||||||
|
DSAParameterSpec dsaParams;
|
||||||
|
if (params == null) {
|
||||||
|
try {
|
||||||
|
dsaParams = ParameterCache.getDSAParameterSpec
|
||||||
|
(keySize, random);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new ProviderException
|
||||||
|
("Could not generate DSA parameters", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dsaParams = (DSAParameterSpec)params;
|
||||||
|
}
|
||||||
|
publicKeyTemplate = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME, dsaParams.getP()),
|
||||||
|
new CK_ATTRIBUTE(CKA_SUBPRIME, dsaParams.getQ()),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE, dsaParams.getG()),
|
||||||
|
};
|
||||||
|
privateKeyTemplate = new CK_ATTRIBUTE[] {
|
||||||
|
// empty
|
||||||
|
};
|
||||||
|
} else if (algorithm.equals("DH")) {
|
||||||
|
keyType = CKK_DH;
|
||||||
|
DHParameterSpec dhParams;
|
||||||
|
int privateBits;
|
||||||
|
if (params == null) {
|
||||||
|
try {
|
||||||
|
dhParams = ParameterCache.getDHParameterSpec
|
||||||
|
(keySize, random);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new ProviderException
|
||||||
|
("Could not generate DH parameters", e);
|
||||||
|
}
|
||||||
|
privateBits = 0;
|
||||||
|
} else {
|
||||||
|
dhParams = (DHParameterSpec)params;
|
||||||
|
privateBits = dhParams.getL();
|
||||||
|
}
|
||||||
|
if (privateBits <= 0) {
|
||||||
|
// XXX find better defaults
|
||||||
|
privateBits = (keySize >= 1024) ? 768 : 512;
|
||||||
|
}
|
||||||
|
publicKeyTemplate = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME, dhParams.getP()),
|
||||||
|
new CK_ATTRIBUTE(CKA_BASE, dhParams.getG())
|
||||||
|
};
|
||||||
|
privateKeyTemplate = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE_BITS, privateBits),
|
||||||
|
};
|
||||||
|
} else if (algorithm.equals("EC")) {
|
||||||
|
keyType = CKK_EC;
|
||||||
|
byte[] encodedParams =
|
||||||
|
P11ECKeyFactory.encodeParameters((ECParameterSpec)params);
|
||||||
|
publicKeyTemplate = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_EC_PARAMS, encodedParams),
|
||||||
|
};
|
||||||
|
privateKeyTemplate = new CK_ATTRIBUTE[] {
|
||||||
|
// empty
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw new ProviderException("Unknown algorithm: " + algorithm);
|
||||||
|
}
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
publicKeyTemplate = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_PUBLIC_KEY, keyType, publicKeyTemplate);
|
||||||
|
privateKeyTemplate = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_PRIVATE_KEY, keyType, privateKeyTemplate);
|
||||||
|
long[] keyIDs = token.p11.C_GenerateKeyPair
|
||||||
|
(session.id(), new CK_MECHANISM(mechanism),
|
||||||
|
publicKeyTemplate, privateKeyTemplate);
|
||||||
|
PublicKey publicKey = P11Key.publicKey
|
||||||
|
(session, keyIDs[0], algorithm, keySize, publicKeyTemplate);
|
||||||
|
PrivateKey privateKey = P11Key.privateKey
|
||||||
|
(session, keyIDs[1], algorithm, keySize, privateKeyTemplate);
|
||||||
|
return new KeyPair(publicKey, privateKey);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException(e);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2689
src/main/java/com/sunyard/security/pkcs11/P11KeyStore.java
Normal file
2689
src/main/java/com/sunyard/security/pkcs11/P11KeyStore.java
Normal file
File diff suppressed because it is too large
Load Diff
269
src/main/java/com/sunyard/security/pkcs11/P11Mac.java
Normal file
269
src/main/java/com/sunyard/security/pkcs11/P11Mac.java
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
|
import javax.crypto.MacSpi;
|
||||||
|
|
||||||
|
import sun.nio.ch.DirectBuffer;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MAC implementation class. This class currently supports HMAC using
|
||||||
|
* MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512 and the SSL3 MAC
|
||||||
|
* using MD5 and SHA-1.
|
||||||
|
*
|
||||||
|
* Note that unlike other classes (e.g. Signature), this does not
|
||||||
|
* composite various operations if the token only supports part of the
|
||||||
|
* required functionality. The MAC implementations in SunJCE already
|
||||||
|
* do exactly that by implementing an MAC on top of MessageDigests. We
|
||||||
|
* could not do any better than they.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11Mac extends MacSpi {
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism object
|
||||||
|
private final CK_MECHANISM ckMechanism;
|
||||||
|
|
||||||
|
// length of the MAC in bytes
|
||||||
|
private final int macLength;
|
||||||
|
|
||||||
|
// key instance used, if operation active
|
||||||
|
private P11Key p11Key;
|
||||||
|
|
||||||
|
// associated session, if any
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
// initialization status
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
|
// one byte buffer for the update(byte) method, initialized on demand
|
||||||
|
private byte[] oneByte;
|
||||||
|
|
||||||
|
P11Mac(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
Long params = null;
|
||||||
|
switch ((int)mechanism) {
|
||||||
|
case (int)CKM_MD5_HMAC:
|
||||||
|
macLength = 16;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA_1_HMAC:
|
||||||
|
macLength = 20;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA224_HMAC:
|
||||||
|
case (int)CKM_SHA512_224_HMAC:
|
||||||
|
macLength = 28;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA256_HMAC:
|
||||||
|
case (int)CKM_SHA512_256_HMAC:
|
||||||
|
macLength = 32;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA384_HMAC:
|
||||||
|
macLength = 48;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SHA512_HMAC:
|
||||||
|
macLength = 64;
|
||||||
|
break;
|
||||||
|
case (int)CKM_SSL3_MD5_MAC:
|
||||||
|
macLength = 16;
|
||||||
|
params = Long.valueOf(16);
|
||||||
|
break;
|
||||||
|
case (int)CKM_SSL3_SHA1_MAC:
|
||||||
|
macLength = 20;
|
||||||
|
params = Long.valueOf(20);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unknown mechanism: " + mechanism);
|
||||||
|
}
|
||||||
|
ckMechanism = new CK_MECHANISM(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the states to the pre-initialized values
|
||||||
|
private void reset(boolean doCancel) {
|
||||||
|
if (!initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCancel && token.explicitCancel) {
|
||||||
|
cancelOperation();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelOperation() {
|
||||||
|
token.ensureValid();
|
||||||
|
// cancel operation by finishing it; avoid killSession as some
|
||||||
|
// hardware vendors may require re-login
|
||||||
|
try {
|
||||||
|
token.p11.C_SignFinal(session.id(), 0);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
if (e.getErrorCode() == CKR_OPERATION_NOT_INITIALIZED) {
|
||||||
|
// Cancel Operation may be invoked after an error on a PKCS#11
|
||||||
|
// call. If the operation inside the token was already cancelled,
|
||||||
|
// do not fail here. This is part of a defensive mechanism for
|
||||||
|
// PKCS#11 libraries that do not strictly follow the standard.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new ProviderException("Cancel failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureInitialized() throws PKCS11Exception {
|
||||||
|
if (!initialized) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() throws PKCS11Exception {
|
||||||
|
if (p11Key == null) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"Operation cannot be performed without calling engineInit first");
|
||||||
|
}
|
||||||
|
token.ensureValid();
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
session = token.getOpSession();
|
||||||
|
}
|
||||||
|
token.p11.C_SignInit(session.id(), ckMechanism, p11KeyID);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineGetMacLength() {
|
||||||
|
return macLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineReset() {
|
||||||
|
reset(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(Key key, AlgorithmParameterSpec params)
|
||||||
|
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||||
|
if (params != null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Parameters not supported");
|
||||||
|
}
|
||||||
|
reset(true);
|
||||||
|
p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm);
|
||||||
|
try {
|
||||||
|
initialize();
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("init() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineDoFinal() {
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
return token.p11.C_SignFinal(session.id(), 0);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// As per the PKCS#11 standard, C_SignFinal may only
|
||||||
|
// keep the operation active on CKR_BUFFER_TOO_SMALL errors or
|
||||||
|
// successful calls to determine the output length. However,
|
||||||
|
// these cases are handled at OpenJDK's libj2pkcs11 native
|
||||||
|
// library. Thus, P11Mac::reset can be called with a 'false'
|
||||||
|
// doCancel argument from here.
|
||||||
|
throw new ProviderException("doFinal() failed", e);
|
||||||
|
} finally {
|
||||||
|
reset(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineUpdate(byte input) {
|
||||||
|
if (oneByte == null) {
|
||||||
|
oneByte = new byte[1];
|
||||||
|
}
|
||||||
|
oneByte[0] = input;
|
||||||
|
engineUpdate(oneByte, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineUpdate(byte[] b, int ofs, int len) {
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("update() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineUpdate(ByteBuffer byteBuffer) {
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
int len = byteBuffer.remaining();
|
||||||
|
if (len <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (byteBuffer instanceof DirectBuffer == false) {
|
||||||
|
super.engineUpdate(byteBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long addr = ((DirectBuffer)byteBuffer).address();
|
||||||
|
int ofs = byteBuffer.position();
|
||||||
|
token.p11.C_SignUpdate(session.id(), addr + ofs, null, 0, len);
|
||||||
|
byteBuffer.position(ofs + len);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("update() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
709
src/main/java/com/sunyard/security/pkcs11/P11PSSSignature.java
Normal file
709
src/main/java/com/sunyard/security/pkcs11/P11PSSSignature.java
Normal file
@ -0,0 +1,709 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import sun.nio.ch.DirectBuffer;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
import java.security.spec.MGF1ParameterSpec;
|
||||||
|
import java.security.spec.PSSParameterSpec;
|
||||||
|
import java.security.interfaces.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSASSA-PSS Signature implementation class. This class currently supports the
|
||||||
|
* following algorithms:
|
||||||
|
*
|
||||||
|
* . RSA-PSS:
|
||||||
|
* . RSASSA-PSS
|
||||||
|
* . SHA1withRSASSA-PSS
|
||||||
|
* . SHA224withRSASSA-PSS
|
||||||
|
* . SHA256withRSASSA-PSS
|
||||||
|
* . SHA384withRSASSA-PSS
|
||||||
|
* . SHA512withRSASSA-PSS
|
||||||
|
*
|
||||||
|
* Note that the underlying PKCS#11 token may support complete signature
|
||||||
|
* algorithm (e.g. CKM_<md>_RSA_PKCS_PSS), or it may just
|
||||||
|
* implement the signature algorithm without hashing (i.e. CKM_RSA_PKCS_PSS).
|
||||||
|
* This class uses what is available and adds whatever extra processing
|
||||||
|
* is needed.
|
||||||
|
*
|
||||||
|
* @since 13
|
||||||
|
*/
|
||||||
|
final class P11PSSSignature extends SignatureSpi {
|
||||||
|
|
||||||
|
private final static boolean DEBUG = false;
|
||||||
|
|
||||||
|
// mappings of digest algorithms and their output length in bytes
|
||||||
|
private static final Hashtable<String, Integer> DIGEST_LENGTHS =
|
||||||
|
new Hashtable<String, Integer>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
DIGEST_LENGTHS.put("SHA-1", 20);
|
||||||
|
DIGEST_LENGTHS.put("SHA", 20);
|
||||||
|
DIGEST_LENGTHS.put("SHA1", 20);
|
||||||
|
DIGEST_LENGTHS.put("SHA-224", 28);
|
||||||
|
DIGEST_LENGTHS.put("SHA224", 28);
|
||||||
|
DIGEST_LENGTHS.put("SHA-256", 32);
|
||||||
|
DIGEST_LENGTHS.put("SHA256", 32);
|
||||||
|
DIGEST_LENGTHS.put("SHA-384", 48);
|
||||||
|
DIGEST_LENGTHS.put("SHA384", 48);
|
||||||
|
DIGEST_LENGTHS.put("SHA-512", 64);
|
||||||
|
DIGEST_LENGTHS.put("SHA512", 64);
|
||||||
|
DIGEST_LENGTHS.put("SHA-512/224", 28);
|
||||||
|
DIGEST_LENGTHS.put("SHA512/224", 28);
|
||||||
|
DIGEST_LENGTHS.put("SHA-512/256", 32);
|
||||||
|
DIGEST_LENGTHS.put("SHA512/256", 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// utility method for comparing digest algorithms
|
||||||
|
// NOTE that first argument is assumed to be standard digest name
|
||||||
|
private static boolean isDigestEqual(String stdAlg, String givenAlg) {
|
||||||
|
if (stdAlg == null || givenAlg == null) return false;
|
||||||
|
|
||||||
|
if (givenAlg.indexOf("-") != -1) {
|
||||||
|
return stdAlg.equalsIgnoreCase(givenAlg);
|
||||||
|
} else {
|
||||||
|
if (stdAlg.equals("SHA-1")) {
|
||||||
|
return (givenAlg.equalsIgnoreCase("SHA")
|
||||||
|
|| givenAlg.equalsIgnoreCase("SHA1"));
|
||||||
|
} else {
|
||||||
|
StringBuilder sb = new StringBuilder(givenAlg);
|
||||||
|
// case-insensitive check
|
||||||
|
if (givenAlg.regionMatches(true, 0, "SHA", 0, 3)) {
|
||||||
|
givenAlg = sb.insert(3, "-").toString();
|
||||||
|
return stdAlg.equalsIgnoreCase(givenAlg);
|
||||||
|
} else {
|
||||||
|
throw new ProviderException("Unsupported digest algorithm "
|
||||||
|
+ givenAlg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// name of the key algorithm, currently just RSA
|
||||||
|
private static final String KEY_ALGO = "RSA";
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private final CK_MECHANISM mechanism;
|
||||||
|
|
||||||
|
// type, one of T_* below
|
||||||
|
private final int type;
|
||||||
|
|
||||||
|
// key instance used, if init*() was called
|
||||||
|
private P11Key p11Key = null;
|
||||||
|
|
||||||
|
// PSS parameters and the flag controlling its access
|
||||||
|
private PSSParameterSpec sigParams = null;
|
||||||
|
private boolean isActive = false;
|
||||||
|
|
||||||
|
// message digest alg, if implied by the algorithm name
|
||||||
|
private final String mdAlg;
|
||||||
|
|
||||||
|
// message digest, if we do the digesting ourselves
|
||||||
|
private MessageDigest md = null;
|
||||||
|
|
||||||
|
// associated session, if any
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
// mode, one of M_* below
|
||||||
|
private int mode;
|
||||||
|
|
||||||
|
// flag indicating whether an operation is initialized
|
||||||
|
private boolean initialized = false;
|
||||||
|
|
||||||
|
// buffer, for update(byte)
|
||||||
|
private final byte[] buffer = new byte[1];
|
||||||
|
|
||||||
|
// total number of bytes processed in current operation
|
||||||
|
private int bytesProcessed = 0;
|
||||||
|
|
||||||
|
// constant for signing mode
|
||||||
|
private final static int M_SIGN = 1;
|
||||||
|
// constant for verification mode
|
||||||
|
private final static int M_VERIFY = 2;
|
||||||
|
|
||||||
|
// constant for type digesting, we do the hashing ourselves
|
||||||
|
private final static int T_DIGEST = 1;
|
||||||
|
// constant for type update, token does everything
|
||||||
|
private final static int T_UPDATE = 2;
|
||||||
|
|
||||||
|
P11PSSSignature(Token token, String algorithm, long mechId)
|
||||||
|
throws NoSuchAlgorithmException, PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = new CK_MECHANISM(mechId);
|
||||||
|
int idx = algorithm.indexOf("with");
|
||||||
|
this.mdAlg = (idx == -1? null : algorithm.substring(0, idx));
|
||||||
|
switch ((int)mechId) {
|
||||||
|
case (int)CKM_SHA1_RSA_PKCS_PSS:
|
||||||
|
case (int)CKM_SHA224_RSA_PKCS_PSS:
|
||||||
|
case (int)CKM_SHA256_RSA_PKCS_PSS:
|
||||||
|
case (int)CKM_SHA384_RSA_PKCS_PSS:
|
||||||
|
case (int)CKM_SHA512_RSA_PKCS_PSS:
|
||||||
|
type = T_UPDATE;
|
||||||
|
break;
|
||||||
|
case (int)CKM_RSA_PKCS_PSS:
|
||||||
|
type = T_DIGEST;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unsupported mechanism: " + mechId);
|
||||||
|
}
|
||||||
|
this.md = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureInitialized() throws SignatureException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (this.p11Key == null) {
|
||||||
|
throw new SignatureException("Missing key");
|
||||||
|
}
|
||||||
|
if (this.sigParams == null) {
|
||||||
|
if (this.mdAlg == null) {
|
||||||
|
// PSS Parameters are required for signature verification
|
||||||
|
throw new SignatureException
|
||||||
|
("Parameters required for RSASSA-PSS signature");
|
||||||
|
} else {
|
||||||
|
int saltLen = DIGEST_LENGTHS.get(this.mdAlg).intValue();
|
||||||
|
// generate default params for both sign and verify?
|
||||||
|
this.sigParams = new PSSParameterSpec(this.mdAlg,
|
||||||
|
"MGF1", new MGF1ParameterSpec(this.mdAlg),
|
||||||
|
saltLen, PSSParameterSpec.TRAILER_FIELD_BC);
|
||||||
|
this.mechanism.setParameter(new CK_RSA_PKCS_PSS_PARAMS(
|
||||||
|
this.mdAlg, "MGF1", this.mdAlg,
|
||||||
|
DIGEST_LENGTHS.get(this.mdAlg).intValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialized == false) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the states to the pre-initialized values
|
||||||
|
private void reset(boolean doCancel) {
|
||||||
|
if (!initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCancel && token.explicitCancel) {
|
||||||
|
cancelOperation();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
mechanism.freeHandle();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
isActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelOperation() {
|
||||||
|
token.ensureValid();
|
||||||
|
if (DEBUG) System.out.print("Cancelling operation");
|
||||||
|
|
||||||
|
// cancel operation by finishing it; avoid killSession as some
|
||||||
|
// hardware vendors may require re-login
|
||||||
|
try {
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
if (type == T_UPDATE) {
|
||||||
|
if (DEBUG) System.out.println(" by C_SignFinal");
|
||||||
|
token.p11.C_SignFinal(session.id(), 0);
|
||||||
|
} else {
|
||||||
|
byte[] digest =
|
||||||
|
(md == null? new byte[0] : md.digest());
|
||||||
|
if (DEBUG) System.out.println(" by C_Sign");
|
||||||
|
token.p11.C_Sign(session.id(), digest);
|
||||||
|
}
|
||||||
|
} else { // M_VERIFY
|
||||||
|
byte[] signature =
|
||||||
|
new byte[(p11Key.length() + 7) >> 3];
|
||||||
|
if (type == T_UPDATE) {
|
||||||
|
if (DEBUG) System.out.println(" by C_VerifyFinal");
|
||||||
|
token.p11.C_VerifyFinal(session.id(), signature);
|
||||||
|
} else {
|
||||||
|
byte[] digest =
|
||||||
|
(md == null? new byte[0] : md.digest());
|
||||||
|
if (DEBUG) System.out.println(" by C_Verify");
|
||||||
|
token.p11.C_Verify(session.id(), digest, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
if (e.getErrorCode() == CKR_OPERATION_NOT_INITIALIZED) {
|
||||||
|
// Cancel Operation may be invoked after an error on a PKCS#11
|
||||||
|
// call. If the operation inside the token was already cancelled,
|
||||||
|
// do not fail here. This is part of a defensive mechanism for
|
||||||
|
// PKCS#11 libraries that do not strictly follow the standard.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
throw new ProviderException("cancel failed", e);
|
||||||
|
}
|
||||||
|
// ignore failure for verification
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumes current state is initialized == false
|
||||||
|
private void initialize() {
|
||||||
|
if (DEBUG) System.out.println("Initializing");
|
||||||
|
|
||||||
|
if (p11Key == null) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"No Key found, call initSign/initVerify first");
|
||||||
|
}
|
||||||
|
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
session = token.getOpSession();
|
||||||
|
}
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
token.p11.C_SignInit(session.id(), mechanism, keyID);
|
||||||
|
} else {
|
||||||
|
token.p11.C_VerifyInit(session.id(), mechanism, keyID);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
throw new ProviderException("Initialization failed", e);
|
||||||
|
}
|
||||||
|
if (bytesProcessed != 0) {
|
||||||
|
bytesProcessed = 0;
|
||||||
|
if (md != null) {
|
||||||
|
md.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
isActive = false;
|
||||||
|
if (DEBUG) System.out.println("Initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkKeySize(Key key) throws InvalidKeyException {
|
||||||
|
if (DEBUG) System.out.print("Checking Key");
|
||||||
|
|
||||||
|
if (!key.getAlgorithm().equals(KEY_ALGO)) {
|
||||||
|
throw new InvalidKeyException("Only " + KEY_ALGO +
|
||||||
|
" keys are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_MECHANISM_INFO mechInfo = null;
|
||||||
|
try {
|
||||||
|
mechInfo = token.getMechanismInfo(mechanism.mechanism);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// should not happen, ignore for now
|
||||||
|
if (DEBUG) {
|
||||||
|
System.out.println("Unexpected exception");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int keySize = 0; // in bytes
|
||||||
|
if (mechInfo != null) {
|
||||||
|
if (key instanceof P11Key) {
|
||||||
|
keySize = (((P11Key) key).length() + 7) >> 3;
|
||||||
|
} else if (key instanceof RSAKey) {
|
||||||
|
keySize = ((RSAKey) key).getModulus().bitLength() >> 3;
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("Unrecognized key type " + key);
|
||||||
|
}
|
||||||
|
// check against available native info which are in bits
|
||||||
|
if ((mechInfo.iMinKeySize != 0) &&
|
||||||
|
(keySize < (mechInfo.iMinKeySize >> 3))) {
|
||||||
|
throw new InvalidKeyException(KEY_ALGO +
|
||||||
|
" key must be at least " + mechInfo.iMinKeySize + " bits");
|
||||||
|
}
|
||||||
|
if ((mechInfo.iMaxKeySize != Integer.MAX_VALUE) &&
|
||||||
|
(keySize > (mechInfo.iMaxKeySize >> 3))) {
|
||||||
|
throw new InvalidKeyException(KEY_ALGO +
|
||||||
|
" key must be at most " + mechInfo.iMaxKeySize + " bits");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.sigParams != null) {
|
||||||
|
String digestAlg = this.sigParams.getDigestAlgorithm();
|
||||||
|
int sLen = this.sigParams.getSaltLength();
|
||||||
|
int hLen = DIGEST_LENGTHS.get(digestAlg).intValue();
|
||||||
|
int minKeyLen = Math.addExact(Math.addExact(sLen, hLen), 2);
|
||||||
|
|
||||||
|
if (keySize < minKeyLen) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key is too short for current params, need min " + minKeyLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSigParams(AlgorithmParameterSpec p)
|
||||||
|
throws InvalidAlgorithmParameterException {
|
||||||
|
if (p == null) {
|
||||||
|
throw new InvalidAlgorithmParameterException("PSS Parameter required");
|
||||||
|
}
|
||||||
|
if (!(p instanceof PSSParameterSpec)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Only PSSParameterSpec is supported");
|
||||||
|
}
|
||||||
|
// no need to validate again if same as current signature parameters
|
||||||
|
PSSParameterSpec params = (PSSParameterSpec) p;
|
||||||
|
if (params == this.sigParams) return;
|
||||||
|
|
||||||
|
String digestAlgorithm = params.getDigestAlgorithm();
|
||||||
|
if (this.mdAlg != null && !isDigestEqual(digestAlgorithm, this.mdAlg)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Digest algorithm in Signature parameters must be " +
|
||||||
|
this.mdAlg);
|
||||||
|
}
|
||||||
|
Integer digestLen = DIGEST_LENGTHS.get(digestAlgorithm);
|
||||||
|
if (digestLen == null) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Unsupported digest algorithm in Signature parameters: " +
|
||||||
|
digestAlgorithm);
|
||||||
|
}
|
||||||
|
if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
|
||||||
|
throw new InvalidAlgorithmParameterException("Only supports MGF1");
|
||||||
|
}
|
||||||
|
if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Only supports TrailerFieldBC(1)");
|
||||||
|
}
|
||||||
|
int saltLen = params.getSaltLength();
|
||||||
|
if (this.p11Key != null) {
|
||||||
|
int maxSaltLen = ((this.p11Key.length() + 7) >> 3) - digestLen.intValue() - 2;
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
System.out.println("Max saltLen = " + maxSaltLen);
|
||||||
|
System.out.println("Curr saltLen = " + saltLen);
|
||||||
|
}
|
||||||
|
if (maxSaltLen < 0 || saltLen > maxSaltLen) {
|
||||||
|
throw new InvalidAlgorithmParameterException("Invalid with current key size");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (DEBUG) System.out.println("No key available for validating saltLen");
|
||||||
|
}
|
||||||
|
|
||||||
|
// validated, now try to store the parameter internally
|
||||||
|
try {
|
||||||
|
this.mechanism.setParameter(
|
||||||
|
new CK_RSA_PKCS_PSS_PARAMS(digestAlgorithm, "MGF1",
|
||||||
|
digestAlgorithm, saltLen));
|
||||||
|
this.sigParams = params;
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
throw new InvalidAlgorithmParameterException(iae);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineInitVerify(PublicKey publicKey)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
|
||||||
|
if (publicKey == null) {
|
||||||
|
throw new InvalidKeyException("Key must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to check key length whenever a new key is set
|
||||||
|
if (publicKey != p11Key) {
|
||||||
|
checkKeySize(publicKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(true);
|
||||||
|
mode = M_VERIFY;
|
||||||
|
p11Key = P11KeyFactory.convertKey(token, publicKey, KEY_ALGO);
|
||||||
|
|
||||||
|
// For PSS, defer PKCS11 initialization calls to update/doFinal as it
|
||||||
|
// needs both key and params
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineInitSign(PrivateKey privateKey)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
|
||||||
|
if (privateKey == null) {
|
||||||
|
throw new InvalidKeyException("Key must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to check RSA key length whenever a new key is set
|
||||||
|
if (privateKey != p11Key) {
|
||||||
|
checkKeySize(privateKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(true);
|
||||||
|
mode = M_SIGN;
|
||||||
|
p11Key = P11KeyFactory.convertKey(token, privateKey, KEY_ALGO);
|
||||||
|
|
||||||
|
// For PSS, defer PKCS11 initialization calls to update/doFinal as it
|
||||||
|
// needs both key and params
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(byte b) throws SignatureException {
|
||||||
|
ensureInitialized();
|
||||||
|
isActive = true;
|
||||||
|
buffer[0] = b;
|
||||||
|
engineUpdate(buffer, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(byte[] b, int ofs, int len)
|
||||||
|
throws SignatureException {
|
||||||
|
ensureInitialized();
|
||||||
|
if (len == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check for overflow
|
||||||
|
if (len + bytesProcessed < 0) {
|
||||||
|
throw new ProviderException("Processed bytes limits exceeded.");
|
||||||
|
}
|
||||||
|
isActive = true;
|
||||||
|
switch (type) {
|
||||||
|
case T_UPDATE:
|
||||||
|
try {
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
if (DEBUG) System.out.println(this + ": Calling C_SignUpdate");
|
||||||
|
token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
|
||||||
|
} else {
|
||||||
|
if (DEBUG) System.out.println(this + ": Calling C_VerfifyUpdate");
|
||||||
|
token.p11.C_VerifyUpdate(session.id(), 0, b, ofs, len);
|
||||||
|
}
|
||||||
|
bytesProcessed += len;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
reset(false);
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case T_DIGEST:
|
||||||
|
// should not happen as this should be covered by earlier checks
|
||||||
|
if (md == null) {
|
||||||
|
throw new ProviderException("PSS Parameters required");
|
||||||
|
}
|
||||||
|
md.update(b, ofs, len);
|
||||||
|
bytesProcessed += len;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(ByteBuffer byteBuffer) {
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
} catch (SignatureException se) {
|
||||||
|
throw new ProviderException(se);
|
||||||
|
}
|
||||||
|
int len = byteBuffer.remaining();
|
||||||
|
if (len <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isActive = true;
|
||||||
|
switch (type) {
|
||||||
|
case T_UPDATE:
|
||||||
|
if (byteBuffer instanceof DirectBuffer == false) {
|
||||||
|
// cannot do better than default impl
|
||||||
|
super.engineUpdate(byteBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long addr = ((DirectBuffer)byteBuffer).address();
|
||||||
|
int ofs = byteBuffer.position();
|
||||||
|
try {
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
if (DEBUG) System.out.println(this + ": Calling C_SignUpdate");
|
||||||
|
token.p11.C_SignUpdate
|
||||||
|
(session.id(), addr + ofs, null, 0, len);
|
||||||
|
} else {
|
||||||
|
if (DEBUG) System.out.println(this + ": Calling C_VerifyUpdate");
|
||||||
|
token.p11.C_VerifyUpdate
|
||||||
|
(session.id(), addr + ofs, null, 0, len);
|
||||||
|
}
|
||||||
|
bytesProcessed += len;
|
||||||
|
byteBuffer.position(ofs + len);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
reset(false);
|
||||||
|
throw new ProviderException("Update failed", e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case T_DIGEST:
|
||||||
|
// should not happen as this should be covered by earlier checks
|
||||||
|
if (md == null) {
|
||||||
|
throw new ProviderException("PSS Parameters required");
|
||||||
|
}
|
||||||
|
md.update(byteBuffer);
|
||||||
|
bytesProcessed += len;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reset(false);
|
||||||
|
throw new ProviderException("Internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected byte[] engineSign() throws SignatureException {
|
||||||
|
ensureInitialized();
|
||||||
|
boolean doCancel = true;
|
||||||
|
if (DEBUG) System.out.print("Generating signature");
|
||||||
|
try {
|
||||||
|
byte[] signature;
|
||||||
|
if (type == T_UPDATE) {
|
||||||
|
if (DEBUG) System.out.println(" by C_SignFinal");
|
||||||
|
signature = token.p11.C_SignFinal(session.id(), 0);
|
||||||
|
} else {
|
||||||
|
if (md == null) {
|
||||||
|
throw new ProviderException("PSS Parameters required");
|
||||||
|
}
|
||||||
|
byte[] digest = md.digest();
|
||||||
|
if (DEBUG) System.out.println(" by C_Sign");
|
||||||
|
signature = token.p11.C_Sign(session.id(), digest);
|
||||||
|
}
|
||||||
|
doCancel = false;
|
||||||
|
return signature;
|
||||||
|
} catch (PKCS11Exception pe) {
|
||||||
|
// As per the PKCS#11 standard, C_Sign and C_SignFinal may only
|
||||||
|
// keep the operation active on CKR_BUFFER_TOO_SMALL errors or
|
||||||
|
// successful calls to determine the output length. However,
|
||||||
|
// these cases are handled at OpenJDK's libj2pkcs11 native
|
||||||
|
// library. Thus, doCancel can safely be 'false' here.
|
||||||
|
doCancel = false;
|
||||||
|
throw new ProviderException(pe);
|
||||||
|
} catch (ProviderException e) {
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
reset(doCancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected boolean engineVerify(byte[] signature) throws SignatureException {
|
||||||
|
ensureInitialized();
|
||||||
|
boolean doCancel = true;
|
||||||
|
if (DEBUG) System.out.print("Verifying signature");
|
||||||
|
try {
|
||||||
|
if (type == T_UPDATE) {
|
||||||
|
if (DEBUG) System.out.println(" by C_VerifyFinal");
|
||||||
|
token.p11.C_VerifyFinal(session.id(), signature);
|
||||||
|
} else {
|
||||||
|
if (md == null) {
|
||||||
|
throw new ProviderException("PSS Parameters required");
|
||||||
|
}
|
||||||
|
byte[] digest = md.digest();
|
||||||
|
if (DEBUG) System.out.println(" by C_Verify");
|
||||||
|
token.p11.C_Verify(session.id(), digest, signature);
|
||||||
|
}
|
||||||
|
doCancel = false;
|
||||||
|
return true;
|
||||||
|
} catch (PKCS11Exception pe) {
|
||||||
|
doCancel = false;
|
||||||
|
long errorCode = pe.getErrorCode();
|
||||||
|
if (errorCode == CKR_SIGNATURE_INVALID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (errorCode == CKR_SIGNATURE_LEN_RANGE) {
|
||||||
|
// return false rather than throwing an exception
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// ECF bug?
|
||||||
|
if (errorCode == CKR_DATA_LEN_RANGE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw new ProviderException(pe);
|
||||||
|
} catch (ProviderException e) {
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
reset(doCancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
protected void engineSetParameter(String param, Object value)
|
||||||
|
throws InvalidParameterException {
|
||||||
|
throw new UnsupportedOperationException("setParameter() not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineSetParameter(AlgorithmParameterSpec params)
|
||||||
|
throws InvalidAlgorithmParameterException {
|
||||||
|
// disallow changing parameters when update has been called
|
||||||
|
if (isActive) {
|
||||||
|
throw new ProviderException
|
||||||
|
("Cannot set parameters during operations");
|
||||||
|
}
|
||||||
|
setSigParams(params);
|
||||||
|
if (type == T_DIGEST) {
|
||||||
|
try {
|
||||||
|
this.md = MessageDigest.getInstance(sigParams.getDigestAlgorithm());
|
||||||
|
} catch (NoSuchAlgorithmException nsae) {
|
||||||
|
throw new InvalidAlgorithmParameterException(nsae);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
protected Object engineGetParameter(String param)
|
||||||
|
throws InvalidParameterException {
|
||||||
|
throw new UnsupportedOperationException("getParameter() not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected AlgorithmParameters engineGetParameters() {
|
||||||
|
if (this.sigParams != null) {
|
||||||
|
try {
|
||||||
|
AlgorithmParameters ap = AlgorithmParameters.getInstance("RSASSA-PSS");
|
||||||
|
ap.init(this.sigParams);
|
||||||
|
return ap;
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
706
src/main/java/com/sunyard/security/pkcs11/P11RSACipher.java
Normal file
706
src/main/java/com/sunyard/security/pkcs11/P11RSACipher.java
Normal file
@ -0,0 +1,706 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
|
||||||
|
import sun.security.util.KeyUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA Cipher implementation class. We currently only support
|
||||||
|
* PKCS#1 v1.5 padding on top of CKM_RSA_PKCS.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11RSACipher extends CipherSpi {
|
||||||
|
|
||||||
|
// minimum length of PKCS#1 v1.5 padding
|
||||||
|
private final static int PKCS1_MIN_PADDING_LENGTH = 11;
|
||||||
|
|
||||||
|
// constant byte[] of length 0
|
||||||
|
private final static byte[] B0 = new byte[0];
|
||||||
|
|
||||||
|
// mode constant for public key encryption
|
||||||
|
private final static int MODE_ENCRYPT = 1;
|
||||||
|
// mode constant for private key decryption
|
||||||
|
private final static int MODE_DECRYPT = 2;
|
||||||
|
// mode constant for private key encryption (signing)
|
||||||
|
private final static int MODE_SIGN = 3;
|
||||||
|
// mode constant for public key decryption (verifying)
|
||||||
|
private final static int MODE_VERIFY = 4;
|
||||||
|
|
||||||
|
// padding type constant for NoPadding
|
||||||
|
private final static int PAD_NONE = 1;
|
||||||
|
// padding type constant for PKCS1Padding
|
||||||
|
private final static int PAD_PKCS1 = 2;
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name (always "RSA")
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private final long mechanism;
|
||||||
|
|
||||||
|
// associated session, if any
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
// mode, one of MODE_* above
|
||||||
|
private int mode;
|
||||||
|
|
||||||
|
// padding, one of PAD_* above
|
||||||
|
private int padType;
|
||||||
|
|
||||||
|
private byte[] buffer;
|
||||||
|
private int bufOfs;
|
||||||
|
|
||||||
|
// key, if init() was called
|
||||||
|
private P11Key p11Key;
|
||||||
|
|
||||||
|
// flag indicating whether an operation is initialized
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
|
// maximum input data size allowed
|
||||||
|
// for decryption, this is the length of the key
|
||||||
|
// for encryption, length of the key minus minimum padding length
|
||||||
|
private int maxInputSize;
|
||||||
|
|
||||||
|
// maximum output size. this is the length of the key
|
||||||
|
private int outputSize;
|
||||||
|
|
||||||
|
// cipher parameter for TLS RSA premaster secret
|
||||||
|
private AlgorithmParameterSpec spec = null;
|
||||||
|
|
||||||
|
// the source of randomness
|
||||||
|
private SecureRandom random;
|
||||||
|
|
||||||
|
P11RSACipher(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = "RSA";
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
// modes do not make sense for RSA, but allow ECB
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
|
||||||
|
if (mode.equalsIgnoreCase("ECB") == false) {
|
||||||
|
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineSetPadding(String padding)
|
||||||
|
throws NoSuchPaddingException {
|
||||||
|
String lowerPadding = padding.toLowerCase(Locale.ENGLISH);
|
||||||
|
if (lowerPadding.equals("pkcs1padding")) {
|
||||||
|
padType = PAD_PKCS1;
|
||||||
|
} else if (lowerPadding.equals("nopadding")) {
|
||||||
|
padType = PAD_NONE;
|
||||||
|
} else {
|
||||||
|
throw new NoSuchPaddingException("Unsupported padding " + padding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return 0 as block size, we are not a block cipher
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineGetBlockSize() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the output size
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineGetOutputSize(int inputLen) {
|
||||||
|
return outputSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no IV, return null
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineGetIV() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no parameters, return null
|
||||||
|
// see JCE spec
|
||||||
|
protected AlgorithmParameters engineGetParameters() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
implInit(opmode, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(int opmode, Key key,
|
||||||
|
AlgorithmParameterSpec params, SecureRandom random)
|
||||||
|
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||||
|
if (params != null) {
|
||||||
|
if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"Parameters not supported");
|
||||||
|
}
|
||||||
|
spec = params;
|
||||||
|
this.random = random; // for TLS RSA premaster secret
|
||||||
|
}
|
||||||
|
implInit(opmode, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
|
||||||
|
SecureRandom random)
|
||||||
|
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||||
|
if (params != null) {
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"Parameters not supported");
|
||||||
|
}
|
||||||
|
implInit(opmode, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void implInit(int opmode, Key key) throws InvalidKeyException {
|
||||||
|
reset(true);
|
||||||
|
p11Key = P11KeyFactory.convertKey(token, key, algorithm);
|
||||||
|
boolean encrypt;
|
||||||
|
if (opmode == Cipher.ENCRYPT_MODE) {
|
||||||
|
encrypt = true;
|
||||||
|
} else if (opmode == Cipher.DECRYPT_MODE) {
|
||||||
|
encrypt = false;
|
||||||
|
} else if (opmode == Cipher.WRAP_MODE) {
|
||||||
|
if (p11Key.isPublic() == false) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Wrap has to be used with public keys");
|
||||||
|
}
|
||||||
|
// No further setup needed for C_Wrap(). We'll initialize later if
|
||||||
|
// we can't use C_Wrap().
|
||||||
|
return;
|
||||||
|
} else if (opmode == Cipher.UNWRAP_MODE) {
|
||||||
|
if (p11Key.isPrivate() == false) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Unwrap has to be used with private keys");
|
||||||
|
}
|
||||||
|
// No further setup needed for C_Unwrap(). We'll initialize later
|
||||||
|
// if we can't use C_Unwrap().
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("Unsupported mode: " + opmode);
|
||||||
|
}
|
||||||
|
if (p11Key.isPublic()) {
|
||||||
|
mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
|
||||||
|
} else if (p11Key.isPrivate()) {
|
||||||
|
mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("Unknown key type: " + p11Key);
|
||||||
|
}
|
||||||
|
int n = (p11Key.length() + 7) >> 3;
|
||||||
|
outputSize = n;
|
||||||
|
buffer = new byte[n];
|
||||||
|
maxInputSize = ((padType == PAD_PKCS1 && encrypt) ?
|
||||||
|
(n - PKCS1_MIN_PADDING_LENGTH) : n);
|
||||||
|
try {
|
||||||
|
initialize();
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("init() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the states to the pre-initialized values
|
||||||
|
private void reset(boolean doCancel) {
|
||||||
|
if (!initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCancel && token.explicitCancel) {
|
||||||
|
cancelOperation();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// should only called by reset as this method does not update other
|
||||||
|
// state variables such as "initialized"
|
||||||
|
private void cancelOperation() {
|
||||||
|
token.ensureValid();
|
||||||
|
// cancel operation by finishing it; avoid killSession as some
|
||||||
|
// hardware vendors may require re-login
|
||||||
|
try {
|
||||||
|
PKCS11 p11 = token.p11;
|
||||||
|
int inLen = maxInputSize;
|
||||||
|
int outLen = buffer.length;
|
||||||
|
long sessId = session.id();
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_ENCRYPT:
|
||||||
|
p11.C_Encrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen);
|
||||||
|
break;
|
||||||
|
case MODE_DECRYPT:
|
||||||
|
p11.C_Decrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen);
|
||||||
|
break;
|
||||||
|
case MODE_SIGN:
|
||||||
|
byte[] tmpBuffer = new byte[maxInputSize];
|
||||||
|
p11.C_Sign(sessId, tmpBuffer);
|
||||||
|
break;
|
||||||
|
case MODE_VERIFY:
|
||||||
|
p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer,
|
||||||
|
0, outLen);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("internal error");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// XXX ensure this always works, ignore error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureInitialized() throws PKCS11Exception {
|
||||||
|
token.ensureValid();
|
||||||
|
if (!initialized) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialize() throws PKCS11Exception {
|
||||||
|
if (p11Key == null) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"Operation cannot be performed without " +
|
||||||
|
"calling engineInit first");
|
||||||
|
}
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
session = token.getOpSession();
|
||||||
|
}
|
||||||
|
PKCS11 p11 = token.p11;
|
||||||
|
CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_ENCRYPT:
|
||||||
|
p11.C_EncryptInit(session.id(), ckMechanism, keyID);
|
||||||
|
break;
|
||||||
|
case MODE_DECRYPT:
|
||||||
|
p11.C_DecryptInit(session.id(), ckMechanism, keyID);
|
||||||
|
break;
|
||||||
|
case MODE_SIGN:
|
||||||
|
p11.C_SignInit(session.id(), ckMechanism, keyID);
|
||||||
|
break;
|
||||||
|
case MODE_VERIFY:
|
||||||
|
p11.C_VerifyRecoverInit(session.id(), ckMechanism, keyID);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AssertionError("internal error");
|
||||||
|
}
|
||||||
|
bufOfs = 0;
|
||||||
|
initialized = true;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void implUpdate(byte[] in, int inOfs, int inLen) {
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("update() failed", e);
|
||||||
|
}
|
||||||
|
if ((inLen == 0) || (in == null)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bufOfs + inLen > maxInputSize) {
|
||||||
|
bufOfs = maxInputSize + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
|
||||||
|
bufOfs += inLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int implDoFinal(byte[] out, int outOfs, int outLen)
|
||||||
|
throws BadPaddingException, IllegalBlockSizeException {
|
||||||
|
if (bufOfs > maxInputSize) {
|
||||||
|
reset(true);
|
||||||
|
throw new IllegalBlockSizeException("Data must not be longer "
|
||||||
|
+ "than " + maxInputSize + " bytes");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ensureInitialized();
|
||||||
|
PKCS11 p11 = token.p11;
|
||||||
|
int n;
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_ENCRYPT:
|
||||||
|
n = p11.C_Encrypt
|
||||||
|
(session.id(), 0, buffer, 0, bufOfs, 0, out, outOfs, outLen);
|
||||||
|
break;
|
||||||
|
case MODE_DECRYPT:
|
||||||
|
n = p11.C_Decrypt
|
||||||
|
(session.id(), 0, buffer, 0, bufOfs, 0, out, outOfs, outLen);
|
||||||
|
break;
|
||||||
|
case MODE_SIGN:
|
||||||
|
byte[] tmpBuffer = new byte[bufOfs];
|
||||||
|
System.arraycopy(buffer, 0, tmpBuffer, 0, bufOfs);
|
||||||
|
tmpBuffer = p11.C_Sign(session.id(), tmpBuffer);
|
||||||
|
if (tmpBuffer.length > outLen) {
|
||||||
|
throw new BadPaddingException(
|
||||||
|
"Output buffer (" + outLen + ") is too small to " +
|
||||||
|
"hold the produced data (" + tmpBuffer.length + ")");
|
||||||
|
}
|
||||||
|
System.arraycopy(tmpBuffer, 0, out, outOfs, tmpBuffer.length);
|
||||||
|
n = tmpBuffer.length;
|
||||||
|
break;
|
||||||
|
case MODE_VERIFY:
|
||||||
|
n = p11.C_VerifyRecover
|
||||||
|
(session.id(), buffer, 0, bufOfs, out, outOfs, outLen);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("internal error");
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw (BadPaddingException)new BadPaddingException
|
||||||
|
("doFinal() failed").initCause(e);
|
||||||
|
} finally {
|
||||||
|
reset(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
|
||||||
|
implUpdate(in, inOfs, inLen);
|
||||||
|
return B0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineUpdate(byte[] in, int inOfs, int inLen,
|
||||||
|
byte[] out, int outOfs) throws ShortBufferException {
|
||||||
|
implUpdate(in, inOfs, inLen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
|
||||||
|
throws IllegalBlockSizeException, BadPaddingException {
|
||||||
|
implUpdate(in, inOfs, inLen);
|
||||||
|
int n = implDoFinal(buffer, 0, buffer.length);
|
||||||
|
byte[] out = new byte[n];
|
||||||
|
System.arraycopy(buffer, 0, out, 0, n);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineDoFinal(byte[] in, int inOfs, int inLen,
|
||||||
|
byte[] out, int outOfs) throws ShortBufferException,
|
||||||
|
IllegalBlockSizeException, BadPaddingException {
|
||||||
|
implUpdate(in, inOfs, inLen);
|
||||||
|
return implDoFinal(out, outOfs, out.length - outOfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] doFinal() throws BadPaddingException,
|
||||||
|
IllegalBlockSizeException {
|
||||||
|
byte[] t = new byte[2048];
|
||||||
|
int n = implDoFinal(t, 0, t.length);
|
||||||
|
byte[] out = new byte[n];
|
||||||
|
System.arraycopy(t, 0, out, 0, n);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected byte[] engineWrap(Key key) throws InvalidKeyException,
|
||||||
|
IllegalBlockSizeException {
|
||||||
|
String keyAlg = key.getAlgorithm();
|
||||||
|
P11Key sKey = null;
|
||||||
|
try {
|
||||||
|
// The conversion may fail, e.g. trying to wrap an AES key on
|
||||||
|
// a token that does not support AES, or when the key size is
|
||||||
|
// not within the range supported by the token.
|
||||||
|
sKey = P11SecretKeyFactory.convertKey(token, key, keyAlg);
|
||||||
|
} catch (InvalidKeyException ike) {
|
||||||
|
byte[] toBeWrappedKey = key.getEncoded();
|
||||||
|
if (toBeWrappedKey == null) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("wrap() failed, no encoding available", ike);
|
||||||
|
}
|
||||||
|
// Directly encrypt the key encoding when key conversion failed
|
||||||
|
implInit(Cipher.ENCRYPT_MODE, p11Key);
|
||||||
|
implUpdate(toBeWrappedKey, 0, toBeWrappedKey.length);
|
||||||
|
try {
|
||||||
|
return doFinal();
|
||||||
|
} catch (BadPaddingException bpe) {
|
||||||
|
// should not occur
|
||||||
|
throw new InvalidKeyException("wrap() failed", bpe);
|
||||||
|
} finally {
|
||||||
|
// Restore original mode
|
||||||
|
implInit(Cipher.WRAP_MODE, p11Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Session s = null;
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
long sKeyID = sKey.getKeyID();
|
||||||
|
try {
|
||||||
|
s = token.getOpSession();
|
||||||
|
return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
|
||||||
|
p11KeyID, sKeyID);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("wrap() failed", e);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
sKey.releaseKeyID();
|
||||||
|
token.releaseSession(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
|
||||||
|
int type) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||||
|
|
||||||
|
boolean isTlsRsaPremasterSecret =
|
||||||
|
algorithm.equals("TlsRsaPremasterSecret");
|
||||||
|
Exception failover = null;
|
||||||
|
|
||||||
|
// Should C_Unwrap be preferred for non-TLS RSA premaster secret?
|
||||||
|
if (token.supportsRawSecretKeyImport()) {
|
||||||
|
// XXX implement unwrap using C_Unwrap() for all keys
|
||||||
|
implInit(Cipher.DECRYPT_MODE, p11Key);
|
||||||
|
try {
|
||||||
|
if (wrappedKey.length > maxInputSize) {
|
||||||
|
throw new InvalidKeyException("Key is too long for unwrapping");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] encoded = null;
|
||||||
|
implUpdate(wrappedKey, 0, wrappedKey.length);
|
||||||
|
try {
|
||||||
|
encoded = doFinal();
|
||||||
|
} catch (BadPaddingException e) {
|
||||||
|
if (isTlsRsaPremasterSecret) {
|
||||||
|
failover = e;
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("Unwrapping failed", e);
|
||||||
|
}
|
||||||
|
} catch (IllegalBlockSizeException e) {
|
||||||
|
// should not occur, handled with length check above
|
||||||
|
throw new InvalidKeyException("Unwrapping failed", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTlsRsaPremasterSecret) {
|
||||||
|
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"No TlsRsaPremasterSecretParameterSpec specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
// polish the TLS premaster secret
|
||||||
|
TlsRsaPremasterSecretParameterSpec psps =
|
||||||
|
(TlsRsaPremasterSecretParameterSpec)spec;
|
||||||
|
encoded = KeyUtil.checkTlsPreMasterSecretKey(
|
||||||
|
psps.getClientVersion(), psps.getServerVersion(),
|
||||||
|
random, encoded, (failover != null));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConstructKeys.constructKey(encoded, algorithm, type);
|
||||||
|
} finally {
|
||||||
|
// Restore original mode
|
||||||
|
implInit(Cipher.UNWRAP_MODE, p11Key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Session s = null;
|
||||||
|
SecretKey secretKey = null;
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
s = token.getObjSession();
|
||||||
|
long keyType = CKK_GENERIC_SECRET;
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes(
|
||||||
|
O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
||||||
|
|
||||||
|
long keyID = token.p11.C_UnwrapKey(s.id(),
|
||||||
|
new CK_MECHANISM(mechanism), p11KeyID,
|
||||||
|
wrappedKey, attributes);
|
||||||
|
secretKey = P11Key.secretKey(s, keyID,
|
||||||
|
algorithm, 48 << 3, attributes);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
if (isTlsRsaPremasterSecret) {
|
||||||
|
failover = e;
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("unwrap() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTlsRsaPremasterSecret) {
|
||||||
|
TlsRsaPremasterSecretParameterSpec psps =
|
||||||
|
(TlsRsaPremasterSecretParameterSpec)spec;
|
||||||
|
|
||||||
|
// Please use the tricky failover as the parameter so that
|
||||||
|
// smart compiler won't dispose the unused variable.
|
||||||
|
secretKey = polishPreMasterSecretKey(token, s,
|
||||||
|
failover, secretKey,
|
||||||
|
psps.getClientVersion(), psps.getServerVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
return secretKey;
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
token.releaseSession(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||||
|
int n = P11KeyFactory.convertKey(token, key, algorithm).length();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SecretKey polishPreMasterSecretKey(
|
||||||
|
Token token, Session session,
|
||||||
|
Exception failover, SecretKey unwrappedKey,
|
||||||
|
int clientVersion, int serverVersion) {
|
||||||
|
|
||||||
|
SecretKey newKey;
|
||||||
|
CK_VERSION version = new CK_VERSION(
|
||||||
|
(clientVersion >>> 8) & 0xFF, clientVersion & 0xFF);
|
||||||
|
try {
|
||||||
|
CK_ATTRIBUTE[] attributes = token.getAttributes(
|
||||||
|
O_GENERATE, CKO_SECRET_KEY,
|
||||||
|
CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
|
||||||
|
long keyID = token.p11.C_GenerateKey(session.id(),
|
||||||
|
new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version),
|
||||||
|
attributes);
|
||||||
|
newKey = P11Key.secretKey(session,
|
||||||
|
keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"Could not generate premaster secret", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (failover == null) ? unwrappedKey : newKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final class ConstructKeys {
|
||||||
|
/**
|
||||||
|
* Construct a public key from its encoding.
|
||||||
|
*
|
||||||
|
* @param encodedKey the encoding of a public key.
|
||||||
|
*
|
||||||
|
* @param encodedKeyAlgorithm the algorithm the encodedKey is for.
|
||||||
|
*
|
||||||
|
* @return a public key constructed from the encodedKey.
|
||||||
|
*/
|
||||||
|
private static final PublicKey constructPublicKey(byte[] encodedKey,
|
||||||
|
String encodedKeyAlgorithm)
|
||||||
|
throws InvalidKeyException, NoSuchAlgorithmException {
|
||||||
|
try {
|
||||||
|
KeyFactory keyFactory =
|
||||||
|
KeyFactory.getInstance(encodedKeyAlgorithm);
|
||||||
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
|
||||||
|
return keyFactory.generatePublic(keySpec);
|
||||||
|
} catch (NoSuchAlgorithmException nsae) {
|
||||||
|
throw new NoSuchAlgorithmException("No installed providers " +
|
||||||
|
"can create keys for the " +
|
||||||
|
encodedKeyAlgorithm +
|
||||||
|
"algorithm", nsae);
|
||||||
|
} catch (InvalidKeySpecException ike) {
|
||||||
|
throw new InvalidKeyException("Cannot construct public key", ike);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a private key from its encoding.
|
||||||
|
*
|
||||||
|
* @param encodedKey the encoding of a private key.
|
||||||
|
*
|
||||||
|
* @param encodedKeyAlgorithm the algorithm the wrapped key is for.
|
||||||
|
*
|
||||||
|
* @return a private key constructed from the encodedKey.
|
||||||
|
*/
|
||||||
|
private static final PrivateKey constructPrivateKey(byte[] encodedKey,
|
||||||
|
String encodedKeyAlgorithm) throws InvalidKeyException,
|
||||||
|
NoSuchAlgorithmException {
|
||||||
|
try {
|
||||||
|
KeyFactory keyFactory =
|
||||||
|
KeyFactory.getInstance(encodedKeyAlgorithm);
|
||||||
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
|
||||||
|
return keyFactory.generatePrivate(keySpec);
|
||||||
|
} catch (NoSuchAlgorithmException nsae) {
|
||||||
|
throw new NoSuchAlgorithmException("No installed providers " +
|
||||||
|
"can create keys for the " +
|
||||||
|
encodedKeyAlgorithm +
|
||||||
|
"algorithm", nsae);
|
||||||
|
} catch (InvalidKeySpecException ike) {
|
||||||
|
throw new InvalidKeyException("Cannot construct private key", ike);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a secret key from its encoding.
|
||||||
|
*
|
||||||
|
* @param encodedKey the encoding of a secret key.
|
||||||
|
*
|
||||||
|
* @param encodedKeyAlgorithm the algorithm the secret key is for.
|
||||||
|
*
|
||||||
|
* @return a secret key constructed from the encodedKey.
|
||||||
|
*/
|
||||||
|
private static final SecretKey constructSecretKey(byte[] encodedKey,
|
||||||
|
String encodedKeyAlgorithm) {
|
||||||
|
return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final Key constructKey(byte[] encoding, String keyAlgorithm,
|
||||||
|
int keyType) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||||
|
switch (keyType) {
|
||||||
|
case Cipher.SECRET_KEY:
|
||||||
|
return constructSecretKey(encoding, keyAlgorithm);
|
||||||
|
case Cipher.PRIVATE_KEY:
|
||||||
|
return constructPrivateKey(encoding, keyAlgorithm);
|
||||||
|
case Cipher.PUBLIC_KEY:
|
||||||
|
return constructPublicKey(encoding, keyAlgorithm);
|
||||||
|
default:
|
||||||
|
throw new InvalidKeyException("Unknown keytype " + keyType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
340
src/main/java/com/sunyard/security/pkcs11/P11RSAKeyFactory.java
Normal file
340
src/main/java/com/sunyard/security/pkcs11/P11RSAKeyFactory.java
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import sun.security.rsa.RSAPublicKeyImpl;
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
import sun.security.rsa.RSAKeyFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA KeyFactory implementation.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11RSAKeyFactory extends P11KeyFactory {
|
||||||
|
|
||||||
|
P11RSAKeyFactory(Token token, String algorithm) {
|
||||||
|
super(token, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicKey implTranslatePublicKey(PublicKey key) throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
if (key instanceof RSAPublicKey) {
|
||||||
|
RSAPublicKey rsaKey = (RSAPublicKey)key;
|
||||||
|
return generatePublic(
|
||||||
|
rsaKey.getModulus(),
|
||||||
|
rsaKey.getPublicExponent()
|
||||||
|
);
|
||||||
|
} else if ("X.509".equals(key.getFormat())) {
|
||||||
|
// let SunRsaSign provider parse for us, then recurse
|
||||||
|
byte[] encoded = key.getEncoded();
|
||||||
|
key = RSAPublicKeyImpl.newKey(encoded);
|
||||||
|
return implTranslatePublicKey(key);
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("PublicKey must be instance "
|
||||||
|
+ "of RSAPublicKey or have X.509 encoding");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create RSA public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateKey implTranslatePrivateKey(PrivateKey key)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
if (key instanceof RSAPrivateCrtKey) {
|
||||||
|
RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;
|
||||||
|
return generatePrivate(
|
||||||
|
rsaKey.getModulus(),
|
||||||
|
rsaKey.getPublicExponent(),
|
||||||
|
rsaKey.getPrivateExponent(),
|
||||||
|
rsaKey.getPrimeP(),
|
||||||
|
rsaKey.getPrimeQ(),
|
||||||
|
rsaKey.getPrimeExponentP(),
|
||||||
|
rsaKey.getPrimeExponentQ(),
|
||||||
|
rsaKey.getCrtCoefficient()
|
||||||
|
);
|
||||||
|
} else if (key instanceof RSAPrivateKey) {
|
||||||
|
RSAPrivateKey rsaKey = (RSAPrivateKey)key;
|
||||||
|
return generatePrivate(
|
||||||
|
rsaKey.getModulus(),
|
||||||
|
rsaKey.getPrivateExponent()
|
||||||
|
);
|
||||||
|
} else if ("PKCS#8".equals(key.getFormat())) {
|
||||||
|
// let SunRsaSign provider parse for us, then recurse
|
||||||
|
byte[] encoded = key.getEncoded();
|
||||||
|
key = sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(encoded);
|
||||||
|
return implTranslatePrivateKey(key);
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException("Private key must be instance "
|
||||||
|
+ "of RSAPrivate(Crt)Key or have PKCS#8 encoding");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create RSA private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected PublicKey engineGeneratePublic(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec instanceof X509EncodedKeySpec) {
|
||||||
|
try {
|
||||||
|
byte[] encoded = ((X509EncodedKeySpec)keySpec).getEncoded();
|
||||||
|
PublicKey key = RSAPublicKeyImpl.newKey(encoded);
|
||||||
|
return implTranslatePublicKey(key);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create RSA public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keySpec instanceof RSAPublicKeySpec == false) {
|
||||||
|
throw new InvalidKeySpecException("Only RSAPublicKeySpec and "
|
||||||
|
+ "X509EncodedKeySpec supported for RSA public keys");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RSAPublicKeySpec rs = (RSAPublicKeySpec)keySpec;
|
||||||
|
return generatePublic(
|
||||||
|
rs.getModulus(),
|
||||||
|
rs.getPublicExponent()
|
||||||
|
);
|
||||||
|
} catch (PKCS11Exception | InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create RSA public key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec instanceof PKCS8EncodedKeySpec) {
|
||||||
|
try {
|
||||||
|
byte[] encoded = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
|
||||||
|
PrivateKey key =
|
||||||
|
sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(encoded);
|
||||||
|
return implTranslatePrivateKey(key);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create RSA private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (keySpec instanceof RSAPrivateCrtKeySpec) {
|
||||||
|
RSAPrivateCrtKeySpec rs = (RSAPrivateCrtKeySpec)keySpec;
|
||||||
|
return generatePrivate(
|
||||||
|
rs.getModulus(),
|
||||||
|
rs.getPublicExponent(),
|
||||||
|
rs.getPrivateExponent(),
|
||||||
|
rs.getPrimeP(),
|
||||||
|
rs.getPrimeQ(),
|
||||||
|
rs.getPrimeExponentP(),
|
||||||
|
rs.getPrimeExponentQ(),
|
||||||
|
rs.getCrtCoefficient()
|
||||||
|
);
|
||||||
|
} else if (keySpec instanceof RSAPrivateKeySpec) {
|
||||||
|
RSAPrivateKeySpec rs = (RSAPrivateKeySpec)keySpec;
|
||||||
|
return generatePrivate(
|
||||||
|
rs.getModulus(),
|
||||||
|
rs.getPrivateExponent()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "
|
||||||
|
+ "and PKCS8EncodedKeySpec supported for RSA private keys");
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception | InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not create RSA private key", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicKey generatePublic(BigInteger n, BigInteger e)
|
||||||
|
throws PKCS11Exception, InvalidKeyException {
|
||||||
|
RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
|
||||||
|
new CK_ATTRIBUTE(CKA_MODULUS, n),
|
||||||
|
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, e),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PUBLIC_KEY, CKK_RSA, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.publicKey
|
||||||
|
(session, keyID, "RSA", n.bitLength(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PrivateKey generatePrivate(BigInteger n, BigInteger d)
|
||||||
|
throws PKCS11Exception, InvalidKeyException {
|
||||||
|
RSAKeyFactory.checkKeyLengths(n.bitLength(), null, -1, 64 * 1024);
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
|
||||||
|
new CK_ATTRIBUTE(CKA_MODULUS, n),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT, d),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PRIVATE_KEY, CKK_RSA, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.privateKey
|
||||||
|
(session, keyID, "RSA", n.bitLength(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PrivateKey generatePrivate(BigInteger n, BigInteger e,
|
||||||
|
BigInteger d, BigInteger p, BigInteger q, BigInteger pe,
|
||||||
|
BigInteger qe, BigInteger coeff) throws PKCS11Exception,
|
||||||
|
InvalidKeyException {
|
||||||
|
RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
|
||||||
|
new CK_ATTRIBUTE(CKA_MODULUS, n),
|
||||||
|
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, e),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT, d),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME_1, p),
|
||||||
|
new CK_ATTRIBUTE(CKA_PRIME_2, q),
|
||||||
|
new CK_ATTRIBUTE(CKA_EXPONENT_1, pe),
|
||||||
|
new CK_ATTRIBUTE(CKA_EXPONENT_2, qe),
|
||||||
|
new CK_ATTRIBUTE(CKA_COEFFICIENT, coeff),
|
||||||
|
};
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_PRIVATE_KEY, CKK_RSA, attributes);
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
return P11Key.privateKey
|
||||||
|
(session, keyID, "RSA", n.bitLength(), attributes);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends KeySpec> T implGetPublicKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException {
|
||||||
|
if (keySpec.isAssignableFrom(RSAPublicKeySpec.class)) {
|
||||||
|
session[0] = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_MODULUS),
|
||||||
|
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
|
||||||
|
};
|
||||||
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
KeySpec spec = new RSAPublicKeySpec(
|
||||||
|
attributes[0].getBigInteger(),
|
||||||
|
attributes[1].getBigInteger()
|
||||||
|
);
|
||||||
|
return keySpec.cast(spec);
|
||||||
|
} else { // X.509 handled in superclass
|
||||||
|
throw new InvalidKeySpecException("Only RSAPublicKeySpec and "
|
||||||
|
+ "X509EncodedKeySpec supported for RSA public keys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<T extends KeySpec> T implGetPrivateKeySpec(P11Key key, Class<T> keySpec,
|
||||||
|
Session[] session) throws PKCS11Exception, InvalidKeySpecException {
|
||||||
|
if (key.sensitive || !key.extractable) {
|
||||||
|
throw new InvalidKeySpecException("Key is sensitive or not extractable");
|
||||||
|
}
|
||||||
|
// If the key is both extractable and not sensitive, then when it was converted into a P11Key
|
||||||
|
// it was also converted into subclass of RSAPrivateKey which encapsulates all of the logic
|
||||||
|
// necessary to retrieve the attributes we need. This sub-class will also cache these attributes
|
||||||
|
// so that we do not need to query them more than once.
|
||||||
|
// Rather than rewrite this logic and make possibly slow calls to the token, we'll just use
|
||||||
|
// that existing logic.
|
||||||
|
if (keySpec.isAssignableFrom(RSAPrivateCrtKeySpec.class)) {
|
||||||
|
// All supported keyspecs (other than PKCS8EncodedKeySpec) descend from RSAPrivateCrtKeySpec
|
||||||
|
if (key instanceof RSAPrivateCrtKey) {
|
||||||
|
RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)key;
|
||||||
|
return keySpec.cast(new RSAPrivateCrtKeySpec(
|
||||||
|
crtKey.getModulus(),
|
||||||
|
crtKey.getPublicExponent(),
|
||||||
|
crtKey.getPrivateExponent(),
|
||||||
|
crtKey.getPrimeP(),
|
||||||
|
crtKey.getPrimeQ(),
|
||||||
|
crtKey.getPrimeExponentP(),
|
||||||
|
crtKey.getPrimeExponentQ(),
|
||||||
|
crtKey.getCrtCoefficient(),
|
||||||
|
crtKey.getParams()
|
||||||
|
));
|
||||||
|
} else { // RSAPrivateKey (non-CRT)
|
||||||
|
if (!keySpec.isAssignableFrom(RSAPrivateKeySpec.class)) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("RSAPrivateCrtKeySpec can only be used with CRT keys");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(key instanceof RSAPrivateKey)) {
|
||||||
|
// We should never reach here as P11Key.privateKey() should always produce an instance
|
||||||
|
// of RSAPrivateKey when the RSA key is both extractable and non-sensitive.
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Key must be an instance of RSAPrivateKeySpec. Was " + key.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall through to RSAPrivateKey (non-CRT)
|
||||||
|
RSAPrivateKey rsaKey = (RSAPrivateKey) key;
|
||||||
|
return keySpec.cast(new RSAPrivateKeySpec(
|
||||||
|
rsaKey.getModulus(),
|
||||||
|
rsaKey.getPrivateExponent(),
|
||||||
|
rsaKey.getParams()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else { // PKCS#8 handled in superclass
|
||||||
|
throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "
|
||||||
|
+ "and PKCS8EncodedKeySpec supported for RSA private keys");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyFactory implGetSoftwareFactory() throws GeneralSecurityException {
|
||||||
|
return KeyFactory.getInstance("RSA", P11Util.getSunRsaSignProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,362 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SecretKeyFactory implementation class. This class currently supports
|
||||||
|
* DES, DESede, AES, ARCFOUR, and Blowfish.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11SecretKeyFactory extends SecretKeyFactorySpi {
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
P11SecretKeyFactory(Token token, String algorithm) {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Map<String,Long> keyTypes;
|
||||||
|
|
||||||
|
static {
|
||||||
|
keyTypes = new HashMap<String,Long>();
|
||||||
|
addKeyType("RC4", CKK_RC4);
|
||||||
|
addKeyType("ARCFOUR", CKK_RC4);
|
||||||
|
addKeyType("DES", CKK_DES);
|
||||||
|
addKeyType("DESede", CKK_DES3);
|
||||||
|
addKeyType("AES", CKK_AES);
|
||||||
|
addKeyType("Blowfish", CKK_BLOWFISH);
|
||||||
|
|
||||||
|
// we don't implement RC2 or IDEA, but we want to be able to generate
|
||||||
|
// keys for those SSL/TLS ciphersuites.
|
||||||
|
addKeyType("RC2", CKK_RC2);
|
||||||
|
addKeyType("IDEA", CKK_IDEA);
|
||||||
|
|
||||||
|
addKeyType("TlsPremasterSecret", PCKK_TLSPREMASTER);
|
||||||
|
addKeyType("TlsRsaPremasterSecret", PCKK_TLSRSAPREMASTER);
|
||||||
|
addKeyType("TlsMasterSecret", PCKK_TLSMASTER);
|
||||||
|
addKeyType("Generic", CKK_GENERIC_SECRET);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addKeyType(String name, long id) {
|
||||||
|
Long l = Long.valueOf(id);
|
||||||
|
keyTypes.put(name, l);
|
||||||
|
keyTypes.put(name.toUpperCase(Locale.ENGLISH), l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long getKeyType(String algorithm) {
|
||||||
|
Long l = keyTypes.get(algorithm);
|
||||||
|
if (l == null) {
|
||||||
|
algorithm = algorithm.toUpperCase(Locale.ENGLISH);
|
||||||
|
l = keyTypes.get(algorithm);
|
||||||
|
if (l == null) {
|
||||||
|
if (algorithm.startsWith("HMAC")) {
|
||||||
|
return PCKK_HMAC;
|
||||||
|
} else if (algorithm.startsWith("SSLMAC")) {
|
||||||
|
return PCKK_SSLMAC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (l != null) ? l.longValue() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an arbitrary key of algorithm into a P11Key of provider.
|
||||||
|
* Used in engineTranslateKey(), P11Cipher.init(), and P11Mac.init().
|
||||||
|
*/
|
||||||
|
static P11Key convertKey(Token token, Key key, String algo)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
return convertKey(token, key, algo, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an arbitrary key of algorithm w/ custom attributes into a
|
||||||
|
* P11Key of provider.
|
||||||
|
* Used in P11KeyStore.storeSkey.
|
||||||
|
*/
|
||||||
|
static P11Key convertKey(Token token, Key key, String algo,
|
||||||
|
CK_ATTRIBUTE[] extraAttrs)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (key == null) {
|
||||||
|
throw new InvalidKeyException("Key must not be null");
|
||||||
|
}
|
||||||
|
if (key instanceof SecretKey == false) {
|
||||||
|
throw new InvalidKeyException("Key must be a SecretKey");
|
||||||
|
}
|
||||||
|
long algoType;
|
||||||
|
if (algo == null) {
|
||||||
|
algo = key.getAlgorithm();
|
||||||
|
algoType = getKeyType(algo);
|
||||||
|
} else {
|
||||||
|
algoType = getKeyType(algo);
|
||||||
|
long keyAlgorithmType = getKeyType(key.getAlgorithm());
|
||||||
|
if (algoType != keyAlgorithmType) {
|
||||||
|
if ((algoType == PCKK_HMAC) || (algoType == PCKK_SSLMAC)) {
|
||||||
|
// ignore key algorithm for MACs
|
||||||
|
} else {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key algorithm must be " + algo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key instanceof P11Key) {
|
||||||
|
P11Key p11Key = (P11Key)key;
|
||||||
|
if (p11Key.token == token) {
|
||||||
|
if (extraAttrs != null) {
|
||||||
|
P11Key newP11Key = null;
|
||||||
|
Session session = null;
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
long newKeyID = token.p11.C_CopyObject(session.id(),
|
||||||
|
p11KeyID, extraAttrs);
|
||||||
|
newP11Key = (P11Key) (P11Key.secretKey(session,
|
||||||
|
newKeyID, p11Key.algorithm, p11Key.keyLength,
|
||||||
|
extraAttrs));
|
||||||
|
} catch (PKCS11Exception p11e) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Cannot duplicate the PKCS11 key", p11e);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
p11Key = newP11Key;
|
||||||
|
}
|
||||||
|
return p11Key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
P11Key p11Key = token.secretCache.get(key);
|
||||||
|
if (p11Key != null) {
|
||||||
|
return p11Key;
|
||||||
|
}
|
||||||
|
if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {
|
||||||
|
throw new InvalidKeyException("Encoded format must be RAW");
|
||||||
|
}
|
||||||
|
byte[] encoded = key.getEncoded();
|
||||||
|
p11Key = createKey(token, encoded, algo, algoType, extraAttrs);
|
||||||
|
token.secretCache.put(key, p11Key);
|
||||||
|
return p11Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fixDESParity(byte[] key, int offset) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
int b = key[offset] & 0xfe;
|
||||||
|
b |= (Integer.bitCount(b) & 1) ^ 1;
|
||||||
|
key[offset++] = (byte)b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static P11Key createKey(Token token, byte[] encoded,
|
||||||
|
String algorithm, long keyType, CK_ATTRIBUTE[] extraAttrs)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
int n = encoded.length << 3;
|
||||||
|
int keyLength = n;
|
||||||
|
try {
|
||||||
|
switch ((int)keyType) {
|
||||||
|
case (int)CKK_DES:
|
||||||
|
keyLength =
|
||||||
|
P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token);
|
||||||
|
fixDESParity(encoded, 0);
|
||||||
|
break;
|
||||||
|
case (int)CKK_DES3:
|
||||||
|
keyLength =
|
||||||
|
P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token);
|
||||||
|
fixDESParity(encoded, 0);
|
||||||
|
fixDESParity(encoded, 8);
|
||||||
|
if (keyLength == 112) {
|
||||||
|
keyType = CKK_DES2;
|
||||||
|
} else {
|
||||||
|
keyType = CKK_DES3;
|
||||||
|
fixDESParity(encoded, 16);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case (int)CKK_AES:
|
||||||
|
keyLength =
|
||||||
|
P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token);
|
||||||
|
break;
|
||||||
|
case (int)CKK_RC4:
|
||||||
|
keyLength =
|
||||||
|
P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token);
|
||||||
|
break;
|
||||||
|
case (int)CKK_BLOWFISH:
|
||||||
|
keyLength =
|
||||||
|
P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n,
|
||||||
|
token);
|
||||||
|
break;
|
||||||
|
case (int)CKK_GENERIC_SECRET:
|
||||||
|
case (int)PCKK_TLSPREMASTER:
|
||||||
|
case (int)PCKK_TLSRSAPREMASTER:
|
||||||
|
case (int)PCKK_TLSMASTER:
|
||||||
|
keyType = CKK_GENERIC_SECRET;
|
||||||
|
break;
|
||||||
|
case (int)PCKK_SSLMAC:
|
||||||
|
case (int)PCKK_HMAC:
|
||||||
|
if (n == 0) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("MAC keys must not be empty");
|
||||||
|
}
|
||||||
|
keyType = CKK_GENERIC_SECRET;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidKeyException("Unknown algorithm " +
|
||||||
|
algorithm);
|
||||||
|
}
|
||||||
|
} catch (InvalidAlgorithmParameterException iape) {
|
||||||
|
throw new InvalidKeyException("Invalid key for " + algorithm,
|
||||||
|
iape);
|
||||||
|
} catch (ProviderException pe) {
|
||||||
|
throw new InvalidKeyException("Could not create key", pe);
|
||||||
|
}
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
CK_ATTRIBUTE[] attributes;
|
||||||
|
if (extraAttrs != null) {
|
||||||
|
attributes = new CK_ATTRIBUTE[3 + extraAttrs.length];
|
||||||
|
System.arraycopy(extraAttrs, 0, attributes, 3,
|
||||||
|
extraAttrs.length);
|
||||||
|
} else {
|
||||||
|
attributes = new CK_ATTRIBUTE[3];
|
||||||
|
}
|
||||||
|
attributes[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY);
|
||||||
|
attributes[1] = new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType);
|
||||||
|
attributes[2] = new CK_ATTRIBUTE(CKA_VALUE, encoded);
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
||||||
|
session = token.getObjSession();
|
||||||
|
long keyID = token.p11.C_CreateObject(session.id(), attributes);
|
||||||
|
P11Key p11Key = (P11Key)P11Key.secretKey
|
||||||
|
(session, keyID, algorithm, keyLength, attributes);
|
||||||
|
return p11Key;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new InvalidKeyException("Could not create key", e);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected SecretKey engineGenerateSecret(KeySpec keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if (keySpec == null) {
|
||||||
|
throw new InvalidKeySpecException("KeySpec must not be null");
|
||||||
|
}
|
||||||
|
if (keySpec instanceof SecretKeySpec) {
|
||||||
|
try {
|
||||||
|
Key key = convertKey(token, (SecretKey)keySpec, algorithm);
|
||||||
|
return (SecretKey)key;
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException(e);
|
||||||
|
}
|
||||||
|
} else if (algorithm.equalsIgnoreCase("DES")) {
|
||||||
|
if (keySpec instanceof DESKeySpec) {
|
||||||
|
byte[] keyBytes = ((DESKeySpec)keySpec).getKey();
|
||||||
|
keySpec = new SecretKeySpec(keyBytes, "DES");
|
||||||
|
return engineGenerateSecret(keySpec);
|
||||||
|
}
|
||||||
|
} else if (algorithm.equalsIgnoreCase("DESede")) {
|
||||||
|
if (keySpec instanceof DESedeKeySpec) {
|
||||||
|
byte[] keyBytes = ((DESedeKeySpec)keySpec).getKey();
|
||||||
|
keySpec = new SecretKeySpec(keyBytes, "DESede");
|
||||||
|
return engineGenerateSecret(keySpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Unsupported spec: " + keySpec.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getKeyBytes(SecretKey key) throws InvalidKeySpecException {
|
||||||
|
try {
|
||||||
|
key = engineTranslateKey(key);
|
||||||
|
if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Could not obtain key bytes");
|
||||||
|
}
|
||||||
|
byte[] k = key.getEncoded();
|
||||||
|
return k;
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpec)
|
||||||
|
throws InvalidKeySpecException {
|
||||||
|
token.ensureValid();
|
||||||
|
if ((key == null) || (keySpec == null)) {
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("key and keySpec must not be null");
|
||||||
|
}
|
||||||
|
if (keySpec.isAssignableFrom(SecretKeySpec.class)) {
|
||||||
|
return new SecretKeySpec(getKeyBytes(key), algorithm);
|
||||||
|
} else if (algorithm.equalsIgnoreCase("DES")) {
|
||||||
|
try {
|
||||||
|
if (keySpec.isAssignableFrom(DESKeySpec.class)) {
|
||||||
|
return new DESKeySpec(getKeyBytes(key));
|
||||||
|
}
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException(e);
|
||||||
|
}
|
||||||
|
} else if (algorithm.equalsIgnoreCase("DESede")) {
|
||||||
|
try {
|
||||||
|
if (keySpec.isAssignableFrom(DESedeKeySpec.class)) {
|
||||||
|
return new DESedeKeySpec(getKeyBytes(key));
|
||||||
|
}
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidKeySpecException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new InvalidKeySpecException
|
||||||
|
("Unsupported spec: " + keySpec.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCE spec
|
||||||
|
protected SecretKey engineTranslateKey(SecretKey key)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
return (SecretKey)convertKey(token, key, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
200
src/main/java/com/sunyard/security/pkcs11/P11SecureRandom.java
Normal file
200
src/main/java/com/sunyard/security/pkcs11/P11SecureRandom.java
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.security.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SecureRandom implementation class. Some tokens support only
|
||||||
|
* C_GenerateRandom() and not C_SeedRandom(). In order not to lose an
|
||||||
|
* application specified seed, we create a SHA1PRNG that we mix with in that
|
||||||
|
* case.
|
||||||
|
*
|
||||||
|
* Note that since SecureRandom is thread safe, we only need one
|
||||||
|
* instance per PKCS#11 token instance. It is created on demand and cached
|
||||||
|
* in the SunPKCS11 class.
|
||||||
|
*
|
||||||
|
* Also note that we obtain the PKCS#11 session on demand, no need to tie one
|
||||||
|
* up.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11SecureRandom extends SecureRandomSpi {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -8939510236124553291L;
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// PRNG for mixing, non-null if active (i.e. setSeed() has been called)
|
||||||
|
private volatile SecureRandom mixRandom;
|
||||||
|
|
||||||
|
// buffer, if mixing is used
|
||||||
|
private byte[] mixBuffer;
|
||||||
|
|
||||||
|
// bytes remaining in mixBuffer, if mixing is used
|
||||||
|
private int buffered;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we buffer data internally for efficiency but limit the lifetime
|
||||||
|
* to avoid using stale bits.
|
||||||
|
*/
|
||||||
|
// lifetime in ms, currently 100 ms (0.1 s)
|
||||||
|
private static final long MAX_IBUFFER_TIME = 100;
|
||||||
|
|
||||||
|
// size of the internal buffer
|
||||||
|
private static final int IBUFFER_SIZE = 32;
|
||||||
|
|
||||||
|
// internal buffer for the random bits
|
||||||
|
private transient byte[] iBuffer = new byte[IBUFFER_SIZE];
|
||||||
|
|
||||||
|
// number of bytes remain in iBuffer
|
||||||
|
private transient int ibuffered = 0;
|
||||||
|
|
||||||
|
// time that data was read into iBuffer
|
||||||
|
private transient long lastRead = 0L;
|
||||||
|
|
||||||
|
P11SecureRandom(Token token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected synchronized void engineSetSeed(byte[] seed) {
|
||||||
|
if (seed == null) {
|
||||||
|
throw new NullPointerException("seed must not be null");
|
||||||
|
}
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
token.p11.C_SeedRandom(session.id(), seed);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// cannot set seed
|
||||||
|
// let a SHA1PRNG use that seed instead
|
||||||
|
SecureRandom random = mixRandom;
|
||||||
|
if (random != null) {
|
||||||
|
random.setSeed(seed);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
mixBuffer = new byte[20];
|
||||||
|
random = SecureRandom.getInstance("SHA1PRNG");
|
||||||
|
// initialize object before assigning to class field
|
||||||
|
random.setSeed(seed);
|
||||||
|
mixRandom = random;
|
||||||
|
} catch (NoSuchAlgorithmException ee) {
|
||||||
|
throw new ProviderException(ee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineNextBytes(byte[] bytes) {
|
||||||
|
if ((bytes == null) || (bytes.length == 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bytes.length <= IBUFFER_SIZE) {
|
||||||
|
int ofs = 0;
|
||||||
|
synchronized (iBuffer) {
|
||||||
|
while (ofs < bytes.length) {
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
// refill the internal buffer if empty or stale
|
||||||
|
if ((ibuffered == 0) ||
|
||||||
|
!(time - lastRead < MAX_IBUFFER_TIME)) {
|
||||||
|
lastRead = time;
|
||||||
|
implNextBytes(iBuffer);
|
||||||
|
ibuffered = IBUFFER_SIZE;
|
||||||
|
}
|
||||||
|
// copy the buffered bytes into 'bytes'
|
||||||
|
while ((ofs < bytes.length) && (ibuffered > 0)) {
|
||||||
|
bytes[ofs++] = iBuffer[IBUFFER_SIZE - ibuffered--];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// avoid using the buffer - just fill bytes directly
|
||||||
|
implNextBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected byte[] engineGenerateSeed(int numBytes) {
|
||||||
|
byte[] b = new byte[numBytes];
|
||||||
|
engineNextBytes(b);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void mix(byte[] b) {
|
||||||
|
SecureRandom random = mixRandom;
|
||||||
|
if (random == null) {
|
||||||
|
// avoid mixing if setSeed() has never been called
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (this) {
|
||||||
|
int ofs = 0;
|
||||||
|
int len = b.length;
|
||||||
|
while (len-- > 0) {
|
||||||
|
if (buffered == 0) {
|
||||||
|
random.nextBytes(mixBuffer);
|
||||||
|
buffered = mixBuffer.length;
|
||||||
|
}
|
||||||
|
b[ofs++] ^= mixBuffer[mixBuffer.length - buffered];
|
||||||
|
buffered--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill up the specified buffer with random bytes, and mix them
|
||||||
|
private void implNextBytes(byte[] bytes) {
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
token.p11.C_GenerateRandom(session.id(), bytes);
|
||||||
|
mix(bytes);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("nextBytes() failed", e);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readObject(ObjectInputStream in)
|
||||||
|
throws IOException, ClassNotFoundException {
|
||||||
|
in.defaultReadObject();
|
||||||
|
// assign default values to non-null transient fields
|
||||||
|
iBuffer = new byte[IBUFFER_SIZE];
|
||||||
|
ibuffered = 0;
|
||||||
|
lastRead = 0L;
|
||||||
|
}
|
||||||
|
}
|
885
src/main/java/com/sunyard/security/pkcs11/P11Signature.java
Normal file
885
src/main/java/com/sunyard/security/pkcs11/P11Signature.java
Normal file
@ -0,0 +1,885 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
import sun.nio.ch.DirectBuffer;
|
||||||
|
|
||||||
|
import sun.security.util.*;
|
||||||
|
import sun.security.x509.AlgorithmId;
|
||||||
|
|
||||||
|
import sun.security.rsa.RSASignature;
|
||||||
|
import sun.security.rsa.RSAPadding;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
import sun.security.util.KeyUtil;
|
||||||
|
|
||||||
|
import javax.crypto.BadPaddingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature implementation class. This class currently supports the
|
||||||
|
* following algorithms:
|
||||||
|
*
|
||||||
|
* . DSA
|
||||||
|
* . NONEwithDSA (RawDSA)
|
||||||
|
* . SHA1withDSA
|
||||||
|
* . RSA:
|
||||||
|
* . MD2withRSA
|
||||||
|
* . MD5withRSA
|
||||||
|
* . SHA1withRSA
|
||||||
|
* . SHA224withRSA
|
||||||
|
* . SHA256withRSA
|
||||||
|
* . SHA384withRSA
|
||||||
|
* . SHA512withRSA
|
||||||
|
* . ECDSA
|
||||||
|
* . NONEwithECDSA
|
||||||
|
* . SHA1withECDSA
|
||||||
|
* . SHA224withECDSA
|
||||||
|
* . SHA256withECDSA
|
||||||
|
* . SHA384withECDSA
|
||||||
|
* . SHA512withECDSA
|
||||||
|
*
|
||||||
|
* Note that the underlying PKCS#11 token may support complete signature
|
||||||
|
* algorithm (e.g. CKM_DSA_SHA1, CKM_MD5_RSA_PKCS), or it may just
|
||||||
|
* implement the signature algorithm without hashing (e.g. CKM_DSA, CKM_PKCS),
|
||||||
|
* or it may only implement the raw public key operation (CKM_RSA_X_509).
|
||||||
|
* This class uses what is available and adds whatever extra processing
|
||||||
|
* is needed.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class P11Signature extends SignatureSpi {
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// name of the key algorithm, currently either RSA or DSA
|
||||||
|
private final String keyAlgorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private final long mechanism;
|
||||||
|
|
||||||
|
// digest algorithm OID, if we encode RSA signature ourselves
|
||||||
|
private final ObjectIdentifier digestOID;
|
||||||
|
|
||||||
|
// type, one of T_* below
|
||||||
|
private final int type;
|
||||||
|
|
||||||
|
// key instance used, if init*() was called
|
||||||
|
private P11Key p11Key;
|
||||||
|
|
||||||
|
// message digest, if we do the digesting ourselves
|
||||||
|
private final MessageDigest md;
|
||||||
|
|
||||||
|
// associated session, if any
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
// mode, one of M_* below
|
||||||
|
private int mode;
|
||||||
|
|
||||||
|
// flag indicating whether an operation is initialized
|
||||||
|
private boolean initialized;
|
||||||
|
|
||||||
|
// buffer, for update(byte) or DSA
|
||||||
|
private final byte[] buffer;
|
||||||
|
|
||||||
|
// total number of bytes processed in current operation
|
||||||
|
private int bytesProcessed;
|
||||||
|
|
||||||
|
// constant for signing mode
|
||||||
|
private final static int M_SIGN = 1;
|
||||||
|
// constant for verification mode
|
||||||
|
private final static int M_VERIFY = 2;
|
||||||
|
|
||||||
|
// constant for type digesting, we do the hashing ourselves
|
||||||
|
private final static int T_DIGEST = 1;
|
||||||
|
// constant for type update, token does everything
|
||||||
|
private final static int T_UPDATE = 2;
|
||||||
|
// constant for type raw, used with RawDSA and NONEwithECDSA only
|
||||||
|
private final static int T_RAW = 3;
|
||||||
|
|
||||||
|
// XXX PKCS#11 v2.20 says "should not be longer than 1024 bits",
|
||||||
|
// but this is a little arbitrary
|
||||||
|
private final static int RAW_ECDSA_MAX = 128;
|
||||||
|
|
||||||
|
P11Signature(Token token, String algorithm, long mechanism)
|
||||||
|
throws NoSuchAlgorithmException, PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
byte[] buffer = null;
|
||||||
|
ObjectIdentifier digestOID = null;
|
||||||
|
MessageDigest md = null;
|
||||||
|
switch ((int)mechanism) {
|
||||||
|
case (int)CKM_MD2_RSA_PKCS:
|
||||||
|
case (int)CKM_MD5_RSA_PKCS:
|
||||||
|
case (int)CKM_SHA1_RSA_PKCS:
|
||||||
|
case (int)CKM_SHA224_RSA_PKCS:
|
||||||
|
case (int)CKM_SHA256_RSA_PKCS:
|
||||||
|
case (int)CKM_SHA384_RSA_PKCS:
|
||||||
|
case (int)CKM_SHA512_RSA_PKCS:
|
||||||
|
keyAlgorithm = "RSA";
|
||||||
|
type = T_UPDATE;
|
||||||
|
buffer = new byte[1];
|
||||||
|
break;
|
||||||
|
case (int)CKM_DSA_SHA1:
|
||||||
|
keyAlgorithm = "DSA";
|
||||||
|
type = T_UPDATE;
|
||||||
|
buffer = new byte[1];
|
||||||
|
break;
|
||||||
|
case (int)CKM_ECDSA_SHA1:
|
||||||
|
keyAlgorithm = "EC";
|
||||||
|
type = T_UPDATE;
|
||||||
|
buffer = new byte[1];
|
||||||
|
break;
|
||||||
|
case (int)CKM_DSA:
|
||||||
|
keyAlgorithm = "DSA";
|
||||||
|
if (algorithm.equals("DSA")) {
|
||||||
|
type = T_DIGEST;
|
||||||
|
md = MessageDigest.getInstance("SHA-1");
|
||||||
|
} else if (algorithm.equals("RawDSA")) {
|
||||||
|
type = T_RAW;
|
||||||
|
buffer = new byte[20];
|
||||||
|
} else {
|
||||||
|
throw new ProviderException(algorithm);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case (int)CKM_ECDSA:
|
||||||
|
keyAlgorithm = "EC";
|
||||||
|
if (algorithm.equals("NONEwithECDSA")) {
|
||||||
|
type = T_RAW;
|
||||||
|
buffer = new byte[RAW_ECDSA_MAX];
|
||||||
|
} else {
|
||||||
|
String digestAlg;
|
||||||
|
if (algorithm.equals("SHA1withECDSA")) {
|
||||||
|
digestAlg = "SHA-1";
|
||||||
|
} else if (algorithm.equals("SHA224withECDSA")) {
|
||||||
|
digestAlg = "SHA-224";
|
||||||
|
} else if (algorithm.equals("SHA256withECDSA")) {
|
||||||
|
digestAlg = "SHA-256";
|
||||||
|
} else if (algorithm.equals("SHA384withECDSA")) {
|
||||||
|
digestAlg = "SHA-384";
|
||||||
|
} else if (algorithm.equals("SHA512withECDSA")) {
|
||||||
|
digestAlg = "SHA-512";
|
||||||
|
} else {
|
||||||
|
throw new ProviderException(algorithm);
|
||||||
|
}
|
||||||
|
type = T_DIGEST;
|
||||||
|
md = MessageDigest.getInstance(digestAlg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case (int)CKM_RSA_PKCS:
|
||||||
|
case (int)CKM_RSA_X_509:
|
||||||
|
keyAlgorithm = "RSA";
|
||||||
|
type = T_DIGEST;
|
||||||
|
if (algorithm.equals("MD5withRSA")) {
|
||||||
|
md = MessageDigest.getInstance("MD5");
|
||||||
|
digestOID = AlgorithmId.MD5_oid;
|
||||||
|
} else if (algorithm.equals("SHA1withRSA")) {
|
||||||
|
md = MessageDigest.getInstance("SHA-1");
|
||||||
|
digestOID = AlgorithmId.SHA_oid;
|
||||||
|
} else if (algorithm.equals("MD2withRSA")) {
|
||||||
|
md = MessageDigest.getInstance("MD2");
|
||||||
|
digestOID = AlgorithmId.MD2_oid;
|
||||||
|
} else if (algorithm.equals("SHA224withRSA")) {
|
||||||
|
md = MessageDigest.getInstance("SHA-224");
|
||||||
|
digestOID = AlgorithmId.SHA224_oid;
|
||||||
|
} else if (algorithm.equals("SHA256withRSA")) {
|
||||||
|
md = MessageDigest.getInstance("SHA-256");
|
||||||
|
digestOID = AlgorithmId.SHA256_oid;
|
||||||
|
} else if (algorithm.equals("SHA384withRSA")) {
|
||||||
|
md = MessageDigest.getInstance("SHA-384");
|
||||||
|
digestOID = AlgorithmId.SHA384_oid;
|
||||||
|
} else if (algorithm.equals("SHA512withRSA")) {
|
||||||
|
md = MessageDigest.getInstance("SHA-512");
|
||||||
|
digestOID = AlgorithmId.SHA512_oid;
|
||||||
|
} else {
|
||||||
|
throw new ProviderException("Unknown signature: " + algorithm);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Unknown mechanism: " + mechanism);
|
||||||
|
}
|
||||||
|
this.buffer = buffer;
|
||||||
|
this.digestOID = digestOID;
|
||||||
|
this.md = md;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the states to the pre-initialized values
|
||||||
|
private void reset(boolean doCancel) {
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialized = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCancel && token.explicitCancel) {
|
||||||
|
cancelOperation();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelOperation() {
|
||||||
|
token.ensureValid();
|
||||||
|
// cancel operation by finishing it; avoid killSession as some
|
||||||
|
// hardware vendors may require re-login
|
||||||
|
try {
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
if (type == T_UPDATE) {
|
||||||
|
token.p11.C_SignFinal(session.id(), 0);
|
||||||
|
} else {
|
||||||
|
byte[] digest;
|
||||||
|
if (type == T_DIGEST) {
|
||||||
|
digest = md.digest();
|
||||||
|
} else { // T_RAW
|
||||||
|
digest = buffer;
|
||||||
|
}
|
||||||
|
token.p11.C_Sign(session.id(), digest);
|
||||||
|
}
|
||||||
|
} else { // M_VERIFY
|
||||||
|
byte[] signature;
|
||||||
|
if (keyAlgorithm.equals("DSA")) {
|
||||||
|
signature = new byte[40];
|
||||||
|
} else {
|
||||||
|
signature = new byte[(p11Key.length() + 7) >> 3];
|
||||||
|
}
|
||||||
|
if (type == T_UPDATE) {
|
||||||
|
token.p11.C_VerifyFinal(session.id(), signature);
|
||||||
|
} else {
|
||||||
|
byte[] digest;
|
||||||
|
if (type == T_DIGEST) {
|
||||||
|
digest = md.digest();
|
||||||
|
} else { // T_RAW
|
||||||
|
digest = buffer;
|
||||||
|
}
|
||||||
|
token.p11.C_Verify(session.id(), digest, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
if (e.getErrorCode() == CKR_OPERATION_NOT_INITIALIZED) {
|
||||||
|
// Cancel Operation may be invoked after an error on a PKCS#11
|
||||||
|
// call. If the operation inside the token was already cancelled,
|
||||||
|
// do not fail here. This is part of a defensive mechanism for
|
||||||
|
// PKCS#11 libraries that do not strictly follow the standard.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mode == M_VERIFY) {
|
||||||
|
long errorCode = e.getErrorCode();
|
||||||
|
if ((errorCode == CKR_SIGNATURE_INVALID) ||
|
||||||
|
(errorCode == CKR_SIGNATURE_LEN_RANGE)) {
|
||||||
|
// expected since signature is incorrect
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ProviderException("cancel failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureInitialized() {
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumes current state is initialized == false
|
||||||
|
private void initialize() {
|
||||||
|
|
||||||
|
if (p11Key == null) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"Operation cannot be performed without " +
|
||||||
|
"calling engineInit first");
|
||||||
|
}
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.ensureValid();
|
||||||
|
if (session == null) {
|
||||||
|
session = token.getOpSession();
|
||||||
|
}
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
token.p11.C_SignInit(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism), keyID);
|
||||||
|
} else {
|
||||||
|
token.p11.C_VerifyInit(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism), keyID);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
throw new ProviderException("Initialization failed", e);
|
||||||
|
}
|
||||||
|
if (bytesProcessed != 0) {
|
||||||
|
bytesProcessed = 0;
|
||||||
|
if (md != null) {
|
||||||
|
md.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkKeySize(String keyAlgo, Key key)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
CK_MECHANISM_INFO mechInfo = null;
|
||||||
|
try {
|
||||||
|
mechInfo = token.getMechanismInfo(mechanism);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// should not happen, ignore for now.
|
||||||
|
}
|
||||||
|
if (mechInfo == null) {
|
||||||
|
// skip the check if no native info available
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int minKeySize = mechInfo.iMinKeySize;
|
||||||
|
int maxKeySize = mechInfo.iMaxKeySize;
|
||||||
|
|
||||||
|
// need to override the MAX keysize for SHA1withDSA
|
||||||
|
if (md != null && mechanism == CKM_DSA && maxKeySize > 1024) {
|
||||||
|
maxKeySize = 1024;
|
||||||
|
}
|
||||||
|
int keySize = 0;
|
||||||
|
if (key instanceof P11Key) {
|
||||||
|
keySize = ((P11Key) key).length();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if (keyAlgo.equals("RSA")) {
|
||||||
|
keySize = ((RSAKey) key).getModulus().bitLength();
|
||||||
|
} else if (keyAlgo.equals("DSA")) {
|
||||||
|
keySize = ((DSAKey) key).getParams().getP().bitLength();
|
||||||
|
} else if (keyAlgo.equals("EC")) {
|
||||||
|
keySize = ((ECKey) key).getParams().getCurve().getField().getFieldSize();
|
||||||
|
} else {
|
||||||
|
throw new ProviderException("Error: unsupported algo " + keyAlgo);
|
||||||
|
}
|
||||||
|
} catch (ClassCastException cce) {
|
||||||
|
throw new InvalidKeyException(keyAlgo +
|
||||||
|
" key must be the right type", cce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keySize < minKeySize) {
|
||||||
|
throw new InvalidKeyException(keyAlgo +
|
||||||
|
" key must be at least " + minKeySize + " bits");
|
||||||
|
}
|
||||||
|
if (keySize > maxKeySize) {
|
||||||
|
throw new InvalidKeyException(keyAlgo +
|
||||||
|
" key must be at most " + maxKeySize + " bits");
|
||||||
|
}
|
||||||
|
if (keyAlgo.equals("RSA")) {
|
||||||
|
checkRSAKeyLength(keySize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkRSAKeyLength(int len) throws InvalidKeyException {
|
||||||
|
RSAPadding padding;
|
||||||
|
try {
|
||||||
|
padding = RSAPadding.getInstance
|
||||||
|
(RSAPadding.PAD_BLOCKTYPE_1, (len + 7) >> 3);
|
||||||
|
} catch (InvalidAlgorithmParameterException iape) {
|
||||||
|
throw new InvalidKeyException(iape.getMessage());
|
||||||
|
}
|
||||||
|
int maxDataSize = padding.getMaxDataSize();
|
||||||
|
int encodedLength;
|
||||||
|
if (algorithm.equals("MD5withRSA") ||
|
||||||
|
algorithm.equals("MD2withRSA")) {
|
||||||
|
encodedLength = 34;
|
||||||
|
} else if (algorithm.equals("SHA1withRSA")) {
|
||||||
|
encodedLength = 35;
|
||||||
|
} else if (algorithm.equals("SHA224withRSA")) {
|
||||||
|
encodedLength = 47;
|
||||||
|
} else if (algorithm.equals("SHA256withRSA")) {
|
||||||
|
encodedLength = 51;
|
||||||
|
} else if (algorithm.equals("SHA384withRSA")) {
|
||||||
|
encodedLength = 67;
|
||||||
|
} else if (algorithm.equals("SHA512withRSA")) {
|
||||||
|
encodedLength = 83;
|
||||||
|
} else {
|
||||||
|
throw new ProviderException("Unknown signature algo: " + algorithm);
|
||||||
|
}
|
||||||
|
if (encodedLength > maxDataSize) {
|
||||||
|
throw new InvalidKeyException
|
||||||
|
("Key is too short for this signature algorithm");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineInitVerify(PublicKey publicKey)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
if (publicKey == null) {
|
||||||
|
throw new InvalidKeyException("Key must not be null");
|
||||||
|
}
|
||||||
|
// Need to check key length whenever a new key is set
|
||||||
|
if (publicKey != p11Key) {
|
||||||
|
checkKeySize(keyAlgorithm, publicKey);
|
||||||
|
}
|
||||||
|
reset(true);
|
||||||
|
mode = M_VERIFY;
|
||||||
|
p11Key = P11KeyFactory.convertKey(token, publicKey, keyAlgorithm);
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineInitSign(PrivateKey privateKey)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
if (privateKey == null) {
|
||||||
|
throw new InvalidKeyException("Key must not be null");
|
||||||
|
}
|
||||||
|
// Need to check RSA key length whenever a new key is set
|
||||||
|
if (privateKey != p11Key) {
|
||||||
|
checkKeySize(keyAlgorithm, privateKey);
|
||||||
|
}
|
||||||
|
reset(true);
|
||||||
|
mode = M_SIGN;
|
||||||
|
p11Key = P11KeyFactory.convertKey(token, privateKey, keyAlgorithm);
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(byte b) throws SignatureException {
|
||||||
|
ensureInitialized();
|
||||||
|
switch (type) {
|
||||||
|
case T_UPDATE:
|
||||||
|
buffer[0] = b;
|
||||||
|
engineUpdate(buffer, 0, 1);
|
||||||
|
break;
|
||||||
|
case T_DIGEST:
|
||||||
|
md.update(b);
|
||||||
|
bytesProcessed++;
|
||||||
|
break;
|
||||||
|
case T_RAW:
|
||||||
|
if (bytesProcessed >= buffer.length) {
|
||||||
|
bytesProcessed = buffer.length + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer[bytesProcessed++] = b;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(byte[] b, int ofs, int len)
|
||||||
|
throws SignatureException {
|
||||||
|
|
||||||
|
ensureInitialized();
|
||||||
|
if (len == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check for overflow
|
||||||
|
if (len + bytesProcessed < 0) {
|
||||||
|
throw new ProviderException("Processed bytes limits exceeded.");
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case T_UPDATE:
|
||||||
|
try {
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
|
||||||
|
} else {
|
||||||
|
token.p11.C_VerifyUpdate(session.id(), 0, b, ofs, len);
|
||||||
|
}
|
||||||
|
bytesProcessed += len;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
reset(false);
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case T_DIGEST:
|
||||||
|
md.update(b, ofs, len);
|
||||||
|
bytesProcessed += len;
|
||||||
|
break;
|
||||||
|
case T_RAW:
|
||||||
|
if (bytesProcessed + len > buffer.length) {
|
||||||
|
bytesProcessed = buffer.length + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.arraycopy(b, ofs, buffer, bytesProcessed, len);
|
||||||
|
bytesProcessed += len;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ProviderException("Internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineUpdate(ByteBuffer byteBuffer) {
|
||||||
|
|
||||||
|
ensureInitialized();
|
||||||
|
int len = byteBuffer.remaining();
|
||||||
|
if (len <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case T_UPDATE:
|
||||||
|
if (byteBuffer instanceof DirectBuffer == false) {
|
||||||
|
// cannot do better than default impl
|
||||||
|
super.engineUpdate(byteBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
long addr = ((DirectBuffer)byteBuffer).address();
|
||||||
|
int ofs = byteBuffer.position();
|
||||||
|
try {
|
||||||
|
if (mode == M_SIGN) {
|
||||||
|
token.p11.C_SignUpdate
|
||||||
|
(session.id(), addr + ofs, null, 0, len);
|
||||||
|
} else {
|
||||||
|
token.p11.C_VerifyUpdate
|
||||||
|
(session.id(), addr + ofs, null, 0, len);
|
||||||
|
}
|
||||||
|
bytesProcessed += len;
|
||||||
|
byteBuffer.position(ofs + len);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
reset(false);
|
||||||
|
throw new ProviderException("Update failed", e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case T_DIGEST:
|
||||||
|
md.update(byteBuffer);
|
||||||
|
bytesProcessed += len;
|
||||||
|
break;
|
||||||
|
case T_RAW:
|
||||||
|
if (bytesProcessed + len > buffer.length) {
|
||||||
|
bytesProcessed = buffer.length + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byteBuffer.get(buffer, bytesProcessed, len);
|
||||||
|
bytesProcessed += len;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reset(false);
|
||||||
|
throw new ProviderException("Internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected byte[] engineSign() throws SignatureException {
|
||||||
|
|
||||||
|
ensureInitialized();
|
||||||
|
boolean doCancel = true;
|
||||||
|
try {
|
||||||
|
byte[] signature;
|
||||||
|
if (type == T_UPDATE) {
|
||||||
|
int len = keyAlgorithm.equals("DSA") ? 40 : 0;
|
||||||
|
signature = token.p11.C_SignFinal(session.id(), len);
|
||||||
|
} else {
|
||||||
|
byte[] digest;
|
||||||
|
if (type == T_DIGEST) {
|
||||||
|
digest = md.digest();
|
||||||
|
} else { // T_RAW
|
||||||
|
if (mechanism == CKM_DSA) {
|
||||||
|
if (bytesProcessed != buffer.length) {
|
||||||
|
throw new SignatureException
|
||||||
|
("Data for RawDSA must be exactly 20 bytes long");
|
||||||
|
}
|
||||||
|
digest = buffer;
|
||||||
|
} else { // CKM_ECDSA
|
||||||
|
if (bytesProcessed > buffer.length) {
|
||||||
|
throw new SignatureException("Data for NONEwithECDSA"
|
||||||
|
+ " must be at most " + RAW_ECDSA_MAX + " bytes long");
|
||||||
|
}
|
||||||
|
digest = new byte[bytesProcessed];
|
||||||
|
System.arraycopy(buffer, 0, digest, 0, bytesProcessed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyAlgorithm.equals("RSA") == false) {
|
||||||
|
// DSA and ECDSA
|
||||||
|
signature = token.p11.C_Sign(session.id(), digest);
|
||||||
|
} else { // RSA
|
||||||
|
byte[] data = encodeSignature(digest);
|
||||||
|
if (mechanism == CKM_RSA_X_509) {
|
||||||
|
data = pkcs1Pad(data);
|
||||||
|
}
|
||||||
|
signature = token.p11.C_Sign(session.id(), data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doCancel = false;
|
||||||
|
|
||||||
|
if (keyAlgorithm.equals("RSA") == false) {
|
||||||
|
return dsaToASN1(signature);
|
||||||
|
} else {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception | BadPaddingException e) {
|
||||||
|
// As per the PKCS#11 standard, C_Sign and C_SignFinal may only
|
||||||
|
// keep the operation active on CKR_BUFFER_TOO_SMALL errors or
|
||||||
|
// successful calls to determine the output length. However,
|
||||||
|
// these cases are handled at OpenJDK's libj2pkcs11 native
|
||||||
|
// library. Thus, doCancel can safely be 'false' here.
|
||||||
|
doCancel = false;
|
||||||
|
throw new ProviderException(e);
|
||||||
|
} finally {
|
||||||
|
reset(doCancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected boolean engineVerify(byte[] signature) throws SignatureException {
|
||||||
|
ensureInitialized();
|
||||||
|
boolean doCancel = true;
|
||||||
|
try {
|
||||||
|
if (keyAlgorithm.equals("DSA")) {
|
||||||
|
signature = asn1ToDSA(signature);
|
||||||
|
} else if (keyAlgorithm.equals("EC")) {
|
||||||
|
signature = asn1ToECDSA(signature);
|
||||||
|
}
|
||||||
|
if (type == T_UPDATE) {
|
||||||
|
token.p11.C_VerifyFinal(session.id(), signature);
|
||||||
|
} else {
|
||||||
|
byte[] digest;
|
||||||
|
if (type == T_DIGEST) {
|
||||||
|
digest = md.digest();
|
||||||
|
} else { // T_RAW
|
||||||
|
if (mechanism == CKM_DSA) {
|
||||||
|
if (bytesProcessed != buffer.length) {
|
||||||
|
throw new SignatureException
|
||||||
|
("Data for RawDSA must be exactly 20 bytes long");
|
||||||
|
}
|
||||||
|
digest = buffer;
|
||||||
|
} else {
|
||||||
|
if (bytesProcessed > buffer.length) {
|
||||||
|
throw new SignatureException("Data for NONEwithECDSA"
|
||||||
|
+ " must be at most " + RAW_ECDSA_MAX + " bytes long");
|
||||||
|
}
|
||||||
|
digest = new byte[bytesProcessed];
|
||||||
|
System.arraycopy(buffer, 0, digest, 0, bytesProcessed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyAlgorithm.equals("RSA") == false) {
|
||||||
|
// DSA and ECDSA
|
||||||
|
token.p11.C_Verify(session.id(), digest, signature);
|
||||||
|
} else { // RSA
|
||||||
|
byte[] data = encodeSignature(digest);
|
||||||
|
if (mechanism == CKM_RSA_X_509) {
|
||||||
|
try {
|
||||||
|
data = pkcs1Pad(data);
|
||||||
|
} catch (BadPaddingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token.p11.C_Verify(session.id(), data, signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doCancel = false;
|
||||||
|
return true;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
doCancel = false;
|
||||||
|
long errorCode = e.getErrorCode();
|
||||||
|
if (errorCode == CKR_SIGNATURE_INVALID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (errorCode == CKR_SIGNATURE_LEN_RANGE) {
|
||||||
|
// return false rather than throwing an exception
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// ECF bug?
|
||||||
|
if (errorCode == CKR_DATA_LEN_RANGE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw new ProviderException(e);
|
||||||
|
} finally {
|
||||||
|
reset(doCancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] pkcs1Pad(byte[] data) throws BadPaddingException {
|
||||||
|
try {
|
||||||
|
int len = (p11Key.length() + 7) >> 3;
|
||||||
|
RSAPadding padding = RSAPadding.getInstance
|
||||||
|
(RSAPadding.PAD_BLOCKTYPE_1, len);
|
||||||
|
byte[] result = padding.pad(data);
|
||||||
|
if (result == null) {
|
||||||
|
throw new ProviderException("Error padding data");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] encodeSignature(byte[] digest) throws SignatureException {
|
||||||
|
try {
|
||||||
|
return RSASignature.encodeSignature(digestOID, digest);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new SignatureException("Invalid encoding", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// private static byte[] decodeSignature(byte[] signature) throws IOException {
|
||||||
|
// return RSASignature.decodeSignature(digestOID, signature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// For DSA and ECDSA signatures, PKCS#11 represents them as a simple
|
||||||
|
// byte array that contains the concatenation of r and s.
|
||||||
|
// For DSA, r and s are always exactly 20 bytes long.
|
||||||
|
// For ECDSA, r and s are of variable length, but we know that each
|
||||||
|
// occupies half of the array.
|
||||||
|
private static byte[] dsaToASN1(byte[] signature) {
|
||||||
|
int n = signature.length >> 1;
|
||||||
|
BigInteger r = new BigInteger(1, P11Util.subarray(signature, 0, n));
|
||||||
|
BigInteger s = new BigInteger(1, P11Util.subarray(signature, n, n));
|
||||||
|
try {
|
||||||
|
DerOutputStream outseq = new DerOutputStream(100);
|
||||||
|
outseq.putInteger(r);
|
||||||
|
outseq.putInteger(s);
|
||||||
|
DerValue result = new DerValue(DerValue.tag_Sequence,
|
||||||
|
outseq.toByteArray());
|
||||||
|
return result.toByteArray();
|
||||||
|
} catch (java.io.IOException e) {
|
||||||
|
throw new RuntimeException("Internal error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] asn1ToDSA(byte[] sig) throws SignatureException {
|
||||||
|
try {
|
||||||
|
// Enforce strict DER checking for signatures
|
||||||
|
DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
|
||||||
|
DerValue[] values = in.getSequence(2);
|
||||||
|
|
||||||
|
// check number of components in the read sequence
|
||||||
|
// and trailing data
|
||||||
|
if ((values.length != 2) || (in.available() != 0)) {
|
||||||
|
throw new IOException("Invalid encoding for signature");
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger r = values[0].getPositiveBigInteger();
|
||||||
|
BigInteger s = values[1].getPositiveBigInteger();
|
||||||
|
|
||||||
|
byte[] br = toByteArray(r, 20);
|
||||||
|
byte[] bs = toByteArray(s, 20);
|
||||||
|
if ((br == null) || (bs == null)) {
|
||||||
|
throw new SignatureException("Out of range value for R or S");
|
||||||
|
}
|
||||||
|
return P11Util.concat(br, bs);
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SignatureException("Invalid encoding for signature", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] asn1ToECDSA(byte[] sig) throws SignatureException {
|
||||||
|
try {
|
||||||
|
// Enforce strict DER checking for signatures
|
||||||
|
DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
|
||||||
|
DerValue[] values = in.getSequence(2);
|
||||||
|
|
||||||
|
// check number of components in the read sequence
|
||||||
|
// and trailing data
|
||||||
|
if ((values.length != 2) || (in.available() != 0)) {
|
||||||
|
throw new IOException("Invalid encoding for signature");
|
||||||
|
}
|
||||||
|
|
||||||
|
BigInteger r = values[0].getPositiveBigInteger();
|
||||||
|
BigInteger s = values[1].getPositiveBigInteger();
|
||||||
|
|
||||||
|
// trim leading zeroes
|
||||||
|
byte[] br = KeyUtil.trimZeroes(r.toByteArray());
|
||||||
|
byte[] bs = KeyUtil.trimZeroes(s.toByteArray());
|
||||||
|
int k = Math.max(br.length, bs.length);
|
||||||
|
// r and s each occupy half the array
|
||||||
|
byte[] res = new byte[k << 1];
|
||||||
|
System.arraycopy(br, 0, res, k - br.length, br.length);
|
||||||
|
System.arraycopy(bs, 0, res, res.length - bs.length, bs.length);
|
||||||
|
return res;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new SignatureException("Invalid encoding for signature", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] toByteArray(BigInteger bi, int len) {
|
||||||
|
byte[] b = bi.toByteArray();
|
||||||
|
int n = b.length;
|
||||||
|
if (n == len) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
if ((n == len + 1) && (b[0] == 0)) {
|
||||||
|
byte[] t = new byte[len];
|
||||||
|
System.arraycopy(b, 1, t, 0, len);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
if (n > len) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// must be smaller
|
||||||
|
byte[] t = new byte[len];
|
||||||
|
System.arraycopy(b, 0, t, (len - n), n);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineSetParameter(String param, Object value)
|
||||||
|
throws InvalidParameterException {
|
||||||
|
throw new UnsupportedOperationException("setParameter() not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected void engineSetParameter(AlgorithmParameterSpec params)
|
||||||
|
throws InvalidAlgorithmParameterException {
|
||||||
|
if (params != null) {
|
||||||
|
throw new InvalidAlgorithmParameterException("No parameter accepted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected Object engineGetParameter(String param)
|
||||||
|
throws InvalidParameterException {
|
||||||
|
throw new UnsupportedOperationException("getParameter() not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// see JCA spec
|
||||||
|
@Override
|
||||||
|
protected AlgorithmParameters engineGetParameters() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import sun.security.internal.spec.*;
|
||||||
|
import sun.security.internal.interfaces.TlsMasterSecret;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyGenerator to calculate the SSL/TLS key material (cipher keys and ivs,
|
||||||
|
* mac keys) from the master secret.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
|
||||||
|
|
||||||
|
private final static String MSG = "TlsKeyMaterialGenerator must be "
|
||||||
|
+ "initialized using a TlsKeyMaterialParameterSpec";
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private long mechanism;
|
||||||
|
|
||||||
|
// parameter spec
|
||||||
|
private TlsKeyMaterialParameterSpec spec;
|
||||||
|
|
||||||
|
// master secret as a P11Key
|
||||||
|
private P11Key p11Key;
|
||||||
|
|
||||||
|
// version, e.g. 0x0301
|
||||||
|
private int version;
|
||||||
|
|
||||||
|
P11TlsKeyMaterialGenerator(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(SecureRandom random) {
|
||||||
|
throw new InvalidParameterException(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(AlgorithmParameterSpec params,
|
||||||
|
SecureRandom random) throws InvalidAlgorithmParameterException {
|
||||||
|
if (params instanceof TlsKeyMaterialParameterSpec == false) {
|
||||||
|
throw new InvalidAlgorithmParameterException(MSG);
|
||||||
|
}
|
||||||
|
this.spec = (TlsKeyMaterialParameterSpec)params;
|
||||||
|
try {
|
||||||
|
p11Key = P11SecretKeyFactory.convertKey
|
||||||
|
(token, spec.getMasterSecret(), "TlsMasterSecret");
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidAlgorithmParameterException("init() failed", e);
|
||||||
|
}
|
||||||
|
version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
|
||||||
|
if ((version < 0x0300) && (version > 0x0303)) {
|
||||||
|
throw new InvalidAlgorithmParameterException("Only SSL 3.0," +
|
||||||
|
" TLS 1.0, TLS 1.1, and TLS 1.2 are supported");
|
||||||
|
}
|
||||||
|
// we assume the token supports both the CKM_SSL3_* and the CKM_TLS_*
|
||||||
|
// mechanisms
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(int keysize, SecureRandom random) {
|
||||||
|
throw new InvalidParameterException(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SecretKey engineGenerateKey() {
|
||||||
|
if (spec == null) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("TlsKeyMaterialGenerator must be initialized");
|
||||||
|
}
|
||||||
|
if (version == 0x0300) {
|
||||||
|
mechanism = CKM_SSL3_KEY_AND_MAC_DERIVE;
|
||||||
|
} else if (version == 0x0301 || version == 0x0302) {
|
||||||
|
mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;
|
||||||
|
}
|
||||||
|
int macBits = spec.getMacKeyLength() << 3;
|
||||||
|
int ivBits = spec.getIvLength() << 3;
|
||||||
|
|
||||||
|
int expandedKeyBits = spec.getExpandedCipherKeyLength() << 3;
|
||||||
|
int keyBits = spec.getCipherKeyLength() << 3;
|
||||||
|
boolean isExportable;
|
||||||
|
if (expandedKeyBits != 0) {
|
||||||
|
isExportable = true;
|
||||||
|
} else {
|
||||||
|
isExportable = false;
|
||||||
|
expandedKeyBits = keyBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_SSL3_RANDOM_DATA random = new CK_SSL3_RANDOM_DATA
|
||||||
|
(spec.getClientRandom(), spec.getServerRandom());
|
||||||
|
Object params = null;
|
||||||
|
CK_MECHANISM ckMechanism = null;
|
||||||
|
if (version < 0x0303) {
|
||||||
|
params = new CK_SSL3_KEY_MAT_PARAMS
|
||||||
|
(macBits, keyBits, ivBits, isExportable, random);
|
||||||
|
ckMechanism = new CK_MECHANISM(mechanism, (CK_SSL3_KEY_MAT_PARAMS)params);
|
||||||
|
} else if (version == 0x0303) {
|
||||||
|
params = new CK_TLS12_KEY_MAT_PARAMS
|
||||||
|
(macBits, keyBits, ivBits, isExportable, random,
|
||||||
|
Functions.getHashMechId(spec.getPRFHashAlg()));
|
||||||
|
ckMechanism = new CK_MECHANISM(mechanism, (CK_TLS12_KEY_MAT_PARAMS)params);
|
||||||
|
}
|
||||||
|
|
||||||
|
String cipherAlgorithm = spec.getCipherAlgorithm();
|
||||||
|
long keyType = P11SecretKeyFactory.getKeyType(cipherAlgorithm);
|
||||||
|
if (keyType < 0) {
|
||||||
|
if (keyBits != 0) {
|
||||||
|
throw new ProviderException
|
||||||
|
("Unknown algorithm: " + spec.getCipherAlgorithm());
|
||||||
|
} else {
|
||||||
|
// NULL encryption ciphersuites
|
||||||
|
keyType = CKK_GENERIC_SECRET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes;
|
||||||
|
if (keyBits != 0) {
|
||||||
|
attributes = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE_LEN, expandedKeyBits >> 3),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// ciphersuites with NULL ciphers
|
||||||
|
attributes = new CK_ATTRIBUTE[0];
|
||||||
|
}
|
||||||
|
attributes = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_DeriveKey(session.id(),
|
||||||
|
ckMechanism, p11KeyID, attributes);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_SSL3_KEY_MAT_OUT out = null;
|
||||||
|
if (params instanceof CK_SSL3_KEY_MAT_PARAMS) {
|
||||||
|
out = ((CK_SSL3_KEY_MAT_PARAMS)params).pReturnedKeyMaterial;
|
||||||
|
} else if (params instanceof CK_TLS12_KEY_MAT_PARAMS) {
|
||||||
|
out = ((CK_TLS12_KEY_MAT_PARAMS)params).pReturnedKeyMaterial;
|
||||||
|
}
|
||||||
|
// Note that the MAC keys do not inherit all attributes from the
|
||||||
|
// template, but they do inherit the sensitive/extractable/token
|
||||||
|
// flags, which is all P11Key cares about.
|
||||||
|
SecretKey clientMacKey, serverMacKey;
|
||||||
|
|
||||||
|
// The MAC size may be zero for GCM mode.
|
||||||
|
//
|
||||||
|
// PKCS11 does not support GCM mode as the author made the comment,
|
||||||
|
// so the macBits is unlikely to be zero. It's only a place holder.
|
||||||
|
if (macBits != 0) {
|
||||||
|
clientMacKey = P11Key.secretKey
|
||||||
|
(session, out.hClientMacSecret, "MAC", macBits, attributes);
|
||||||
|
serverMacKey = P11Key.secretKey
|
||||||
|
(session, out.hServerMacSecret, "MAC", macBits, attributes);
|
||||||
|
} else {
|
||||||
|
clientMacKey = null;
|
||||||
|
serverMacKey = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecretKey clientCipherKey, serverCipherKey;
|
||||||
|
if (keyBits != 0) {
|
||||||
|
clientCipherKey = P11Key.secretKey(session, out.hClientKey,
|
||||||
|
cipherAlgorithm, expandedKeyBits, attributes);
|
||||||
|
serverCipherKey = P11Key.secretKey(session, out.hServerKey,
|
||||||
|
cipherAlgorithm, expandedKeyBits, attributes);
|
||||||
|
} else {
|
||||||
|
clientCipherKey = null;
|
||||||
|
serverCipherKey = null;
|
||||||
|
}
|
||||||
|
IvParameterSpec clientIv = (out.pIVClient == null)
|
||||||
|
? null : new IvParameterSpec(out.pIVClient);
|
||||||
|
IvParameterSpec serverIv = (out.pIVServer == null)
|
||||||
|
? null : new IvParameterSpec(out.pIVServer);
|
||||||
|
|
||||||
|
return new TlsKeyMaterialSpec(clientMacKey, serverMacKey,
|
||||||
|
clientCipherKey, clientIv, serverCipherKey, serverIv);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ProviderException("Could not generate key", e);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import sun.security.internal.spec.TlsMasterSecretParameterSpec;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyGenerator for the SSL/TLS master secret.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
|
||||||
|
|
||||||
|
private final static String MSG = "TlsMasterSecretGenerator must be "
|
||||||
|
+ "initialized using a TlsMasterSecretParameterSpec";
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private long mechanism;
|
||||||
|
|
||||||
|
private TlsMasterSecretParameterSpec spec;
|
||||||
|
private P11Key p11Key;
|
||||||
|
|
||||||
|
int version;
|
||||||
|
|
||||||
|
P11TlsMasterSecretGenerator(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(SecureRandom random) {
|
||||||
|
throw new InvalidParameterException(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(AlgorithmParameterSpec params,
|
||||||
|
SecureRandom random) throws InvalidAlgorithmParameterException {
|
||||||
|
if (params instanceof TlsMasterSecretParameterSpec == false) {
|
||||||
|
throw new InvalidAlgorithmParameterException(MSG);
|
||||||
|
}
|
||||||
|
this.spec = (TlsMasterSecretParameterSpec)params;
|
||||||
|
SecretKey key = spec.getPremasterSecret();
|
||||||
|
// algorithm should be either TlsRsaPremasterSecret or TlsPremasterSecret,
|
||||||
|
// but we omit the check
|
||||||
|
try {
|
||||||
|
p11Key = P11SecretKeyFactory.convertKey(token, key, null);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidAlgorithmParameterException("init() failed", e);
|
||||||
|
}
|
||||||
|
version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
|
||||||
|
if ((version < 0x0300) && (version > 0x0303)) {
|
||||||
|
throw new InvalidAlgorithmParameterException("Only SSL 3.0," +
|
||||||
|
" TLS 1.0, TLS 1.1, and TLS 1.2 are supported");
|
||||||
|
}
|
||||||
|
// We assume the token supports the required mechanism. If it does not,
|
||||||
|
// generateKey() will fail and the failover should take care of us.
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(int keysize, SecureRandom random) {
|
||||||
|
throw new InvalidParameterException(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SecretKey engineGenerateKey() {
|
||||||
|
if (spec == null) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("TlsMasterSecretGenerator must be initialized");
|
||||||
|
}
|
||||||
|
final boolean isTlsRsaPremasterSecret =
|
||||||
|
p11Key.getAlgorithm().equals("TlsRsaPremasterSecret");
|
||||||
|
if (version == 0x0300) {
|
||||||
|
mechanism = isTlsRsaPremasterSecret ?
|
||||||
|
CKM_SSL3_MASTER_KEY_DERIVE : CKM_SSL3_MASTER_KEY_DERIVE_DH;
|
||||||
|
} else if (version == 0x0301 || version == 0x0302) {
|
||||||
|
mechanism = isTlsRsaPremasterSecret ?
|
||||||
|
CKM_TLS_MASTER_KEY_DERIVE : CKM_TLS_MASTER_KEY_DERIVE_DH;
|
||||||
|
} else if (version == 0x0303) {
|
||||||
|
mechanism = isTlsRsaPremasterSecret ?
|
||||||
|
CKM_TLS12_MASTER_KEY_DERIVE : CKM_TLS12_MASTER_KEY_DERIVE_DH;
|
||||||
|
}
|
||||||
|
CK_VERSION ckVersion;
|
||||||
|
if (isTlsRsaPremasterSecret) {
|
||||||
|
ckVersion = new CK_VERSION(0, 0);
|
||||||
|
} else {
|
||||||
|
// Note: we use DH for all non-RSA premaster secrets. That includes
|
||||||
|
// Kerberos. That should not be a problem because master secret
|
||||||
|
// calculation is always a straightforward application of the
|
||||||
|
// TLS PRF (or the SSL equivalent).
|
||||||
|
// The only thing special about RSA master secret calculation is
|
||||||
|
// that it extracts the version numbers from the premaster secret.
|
||||||
|
ckVersion = null;
|
||||||
|
}
|
||||||
|
byte[] clientRandom = spec.getClientRandom();
|
||||||
|
byte[] serverRandom = spec.getServerRandom();
|
||||||
|
CK_SSL3_RANDOM_DATA random =
|
||||||
|
new CK_SSL3_RANDOM_DATA(clientRandom, serverRandom);
|
||||||
|
CK_MECHANISM ckMechanism = null;
|
||||||
|
if (version < 0x0303) {
|
||||||
|
CK_SSL3_MASTER_KEY_DERIVE_PARAMS params =
|
||||||
|
new CK_SSL3_MASTER_KEY_DERIVE_PARAMS(random, ckVersion);
|
||||||
|
ckMechanism = new CK_MECHANISM(mechanism, params);
|
||||||
|
} else if (version == 0x0303) {
|
||||||
|
CK_TLS12_MASTER_KEY_DERIVE_PARAMS params =
|
||||||
|
new CK_TLS12_MASTER_KEY_DERIVE_PARAMS(random, ckVersion,
|
||||||
|
Functions.getHashMechId(spec.getPRFHashAlg()));
|
||||||
|
ckMechanism = new CK_MECHANISM(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session session = null;
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = token.getAttributes(O_GENERATE,
|
||||||
|
CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
|
||||||
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
|
ckMechanism, p11KeyID, attributes);
|
||||||
|
int major, minor;
|
||||||
|
if (ckVersion == null) {
|
||||||
|
major = -1;
|
||||||
|
minor = -1;
|
||||||
|
} else {
|
||||||
|
major = ckVersion.major;
|
||||||
|
minor = ckVersion.minor;
|
||||||
|
}
|
||||||
|
return P11Key.masterSecretKey(session, keyID,
|
||||||
|
"TlsMasterSecret", 48 << 3, attributes, major, minor);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ProviderException("Could not generate key", e);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import sun.security.internal.spec.TlsPrfParameterSpec;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyGenerator for the TLS PRF. Note that although the PRF is used in a number
|
||||||
|
* of places during the handshake, this class is usually only used to calculate
|
||||||
|
* the Finished messages. The reason is that for those other uses more specific
|
||||||
|
* PKCS#11 mechanisms have been defined (CKM_SSL3_MASTER_KEY_DERIVE, etc.).
|
||||||
|
*
|
||||||
|
* <p>This class supports the CKM_TLS_PRF mechanism from PKCS#11 v2.20 and
|
||||||
|
* the older NSS private mechanism.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
final class P11TlsPrfGenerator extends KeyGeneratorSpi {
|
||||||
|
|
||||||
|
private final static String MSG =
|
||||||
|
"TlsPrfGenerator must be initialized using a TlsPrfParameterSpec";
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private final long mechanism;
|
||||||
|
|
||||||
|
private TlsPrfParameterSpec spec;
|
||||||
|
|
||||||
|
private P11Key p11Key;
|
||||||
|
|
||||||
|
P11TlsPrfGenerator(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(SecureRandom random) {
|
||||||
|
throw new InvalidParameterException(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(AlgorithmParameterSpec params,
|
||||||
|
SecureRandom random) throws InvalidAlgorithmParameterException {
|
||||||
|
if (params instanceof TlsPrfParameterSpec == false) {
|
||||||
|
throw new InvalidAlgorithmParameterException(MSG);
|
||||||
|
}
|
||||||
|
this.spec = (TlsPrfParameterSpec)params;
|
||||||
|
SecretKey key = spec.getSecret();
|
||||||
|
if (key == null) {
|
||||||
|
key = NULL_KEY;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
p11Key = P11SecretKeyFactory.convertKey(token, key, null);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new InvalidAlgorithmParameterException("init() failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecretKeySpec does not allow zero length keys, so we define our
|
||||||
|
// own class.
|
||||||
|
//
|
||||||
|
// As an anonymous class cannot make any guarantees about serialization
|
||||||
|
// compatibility, it is nonsensical for an anonymous class to define a
|
||||||
|
// serialVersionUID. Suppress warnings relative to missing serialVersionUID
|
||||||
|
// field in the anonymous subclass of serializable SecretKey.
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
private static final SecretKey NULL_KEY = new SecretKey() {
|
||||||
|
public byte[] getEncoded() {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
public String getFormat() {
|
||||||
|
return "RAW";
|
||||||
|
}
|
||||||
|
public String getAlgorithm() {
|
||||||
|
return "Generic";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected void engineInit(int keysize, SecureRandom random) {
|
||||||
|
throw new InvalidParameterException(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SecretKey engineGenerateKey() {
|
||||||
|
if (spec == null) {
|
||||||
|
throw new IllegalStateException("TlsPrfGenerator must be initialized");
|
||||||
|
}
|
||||||
|
byte[] seed = spec.getSeed();
|
||||||
|
|
||||||
|
// TLS 1.2
|
||||||
|
if (mechanism == CKM_TLS_MAC) {
|
||||||
|
SecretKey k = null;
|
||||||
|
int ulServerOrClient = 0;
|
||||||
|
if (spec.getLabel().equals("server finished")) {
|
||||||
|
ulServerOrClient = 1;
|
||||||
|
}
|
||||||
|
if (spec.getLabel().equals("client finished")) {
|
||||||
|
ulServerOrClient = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ulServerOrClient != 0) {
|
||||||
|
// Finished message
|
||||||
|
CK_TLS_MAC_PARAMS params = new CK_TLS_MAC_PARAMS(
|
||||||
|
Functions.getHashMechId(spec.getPRFHashAlg()),
|
||||||
|
spec.getOutputLength(), ulServerOrClient);
|
||||||
|
Session session = null;
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
token.p11.C_SignInit(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism, params), keyID);
|
||||||
|
token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
|
||||||
|
byte[] out = token.p11.C_SignFinal
|
||||||
|
(session.id(), spec.getOutputLength());
|
||||||
|
return new SecretKeySpec(out, "TlsPrf");
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Could not calculate PRF", e);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ProviderException("Only Finished message authentication code"+
|
||||||
|
" generation supported for TLS 1.2.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] label = P11Util.getBytesUTF8(spec.getLabel());
|
||||||
|
|
||||||
|
if (mechanism == CKM_NSS_TLS_PRF_GENERAL) {
|
||||||
|
Session session = null;
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
token.p11.C_SignInit
|
||||||
|
(session.id(), new CK_MECHANISM(mechanism), keyID);
|
||||||
|
token.p11.C_SignUpdate(session.id(), 0, label, 0, label.length);
|
||||||
|
token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
|
||||||
|
byte[] out = token.p11.C_SignFinal
|
||||||
|
(session.id(), spec.getOutputLength());
|
||||||
|
return new SecretKeySpec(out, "TlsPrf");
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Could not calculate PRF", e);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mechanism == CKM_TLS_PRF
|
||||||
|
|
||||||
|
byte[] out = new byte[spec.getOutputLength()];
|
||||||
|
CK_TLS_PRF_PARAMS params = new CK_TLS_PRF_PARAMS(seed, label, out);
|
||||||
|
|
||||||
|
Session session = null;
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
token.p11.C_DeriveKey(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism, params), keyID, null);
|
||||||
|
return new SecretKeySpec(out, "TlsPrf");
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Could not calculate PRF", e);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
|
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyGenerator for the SSL/TLS RSA premaster secret.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
|
||||||
|
|
||||||
|
private final static String MSG = "TlsRsaPremasterSecretGenerator must be "
|
||||||
|
+ "initialized using a TlsRsaPremasterSecretParameterSpec";
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// algorithm name
|
||||||
|
private final String algorithm;
|
||||||
|
|
||||||
|
// mechanism id
|
||||||
|
private long mechanism;
|
||||||
|
|
||||||
|
private int version;
|
||||||
|
|
||||||
|
private TlsRsaPremasterSecretParameterSpec spec;
|
||||||
|
|
||||||
|
P11TlsRsaPremasterSecretGenerator(Token token, String algorithm, long mechanism)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
super();
|
||||||
|
this.token = token;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(SecureRandom random) {
|
||||||
|
throw new InvalidParameterException(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(AlgorithmParameterSpec params,
|
||||||
|
SecureRandom random) throws InvalidAlgorithmParameterException {
|
||||||
|
if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
|
||||||
|
throw new InvalidAlgorithmParameterException(MSG);
|
||||||
|
}
|
||||||
|
this.spec = (TlsRsaPremasterSecretParameterSpec)params;
|
||||||
|
version = (spec.getMajorVersion() << 8) | spec.getMinorVersion();
|
||||||
|
if ((version < 0x0300) && (version > 0x0303)) {
|
||||||
|
throw new InvalidAlgorithmParameterException
|
||||||
|
("Only SSL 3.0, TLS 1.0, TLS 1.1, and TLS 1.2 are supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(int keysize, SecureRandom random) {
|
||||||
|
throw new InvalidParameterException(MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only can be used in client side to generate TLS RSA premaster secret.
|
||||||
|
protected SecretKey engineGenerateKey() {
|
||||||
|
if (spec == null) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("TlsRsaPremasterSecretGenerator must be initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_VERSION version = new CK_VERSION(
|
||||||
|
spec.getMajorVersion(), spec.getMinorVersion());
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
CK_ATTRIBUTE[] attributes = token.getAttributes(
|
||||||
|
O_GENERATE, CKO_SECRET_KEY,
|
||||||
|
CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
|
||||||
|
long keyID = token.p11.C_GenerateKey(session.id(),
|
||||||
|
new CK_MECHANISM(mechanism, version), attributes);
|
||||||
|
SecretKey key = P11Key.secretKey(session,
|
||||||
|
keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
|
||||||
|
return key;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"Could not generate premaster secret", e);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
181
src/main/java/com/sunyard/security/pkcs11/P11Util.java
Normal file
181
src/main/java/com/sunyard/security/pkcs11/P11Util.java
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of static utility methods.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public final class P11Util {
|
||||||
|
|
||||||
|
private static Object LOCK = new Object();
|
||||||
|
|
||||||
|
private static volatile Provider sun, sunRsaSign, sunJce;
|
||||||
|
|
||||||
|
private P11Util() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
static Provider getSunProvider() {
|
||||||
|
Provider p = sun;
|
||||||
|
if (p == null) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
p = getProvider
|
||||||
|
(sun, "SUN", "sun.security.provider.Sun");
|
||||||
|
sun = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Provider getSunRsaSignProvider() {
|
||||||
|
Provider p = sunRsaSign;
|
||||||
|
if (p == null) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
p = getProvider
|
||||||
|
(sunRsaSign, "SunRsaSign", "sun.security.rsa.SunRsaSign");
|
||||||
|
sunRsaSign = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Provider getSunJceProvider() {
|
||||||
|
Provider p = sunJce;
|
||||||
|
if (p == null) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
p = getProvider
|
||||||
|
(sunJce, "SunJCE", "com.sun.crypto.provider.SunJCE");
|
||||||
|
sunJce = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Provider getProvider(Provider p, String providerName,
|
||||||
|
String className) {
|
||||||
|
if (p != null) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
p = Security.getProvider(providerName);
|
||||||
|
if (p == null) {
|
||||||
|
try {
|
||||||
|
Class<?> clazz = Class.forName(className);
|
||||||
|
p = (Provider)clazz.newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ProviderException
|
||||||
|
("Could not find provider " + providerName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] convert(byte[] input, int offset, int len) {
|
||||||
|
if ((offset == 0) && (len == input.length)) {
|
||||||
|
return input;
|
||||||
|
} else {
|
||||||
|
byte[] t = new byte[len];
|
||||||
|
System.arraycopy(input, offset, t, 0, len);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] subarray(byte[] b, int ofs, int len) {
|
||||||
|
byte[] out = new byte[len];
|
||||||
|
System.arraycopy(b, ofs, out, 0, len);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] concat(byte[] b1, byte[] b2) {
|
||||||
|
byte[] b = new byte[b1.length + b2.length];
|
||||||
|
System.arraycopy(b1, 0, b, 0, b1.length);
|
||||||
|
System.arraycopy(b2, 0, b, b1.length, b2.length);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long[] concat(long[] b1, long[] b2) {
|
||||||
|
if (b1.length == 0) {
|
||||||
|
return b2;
|
||||||
|
}
|
||||||
|
long[] b = new long[b1.length + b2.length];
|
||||||
|
System.arraycopy(b1, 0, b, 0, b1.length);
|
||||||
|
System.arraycopy(b2, 0, b, b1.length, b2.length);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] getMagnitude(BigInteger bi) {
|
||||||
|
byte[] b = bi.toByteArray();
|
||||||
|
if ((b.length > 1) && (b[0] == 0)) {
|
||||||
|
int n = b.length - 1;
|
||||||
|
byte[] newarray = new byte[n];
|
||||||
|
System.arraycopy(b, 1, newarray, 0, n);
|
||||||
|
b = newarray;
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] getBytesUTF8(String s) {
|
||||||
|
try {
|
||||||
|
return s.getBytes("UTF8");
|
||||||
|
} catch (java.io.UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] sha1(byte[] data) {
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||||
|
md.update(data);
|
||||||
|
return md.digest();
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static char[] hexDigits = "0123456789abcdef".toCharArray();
|
||||||
|
|
||||||
|
static String toString(byte[] b) {
|
||||||
|
if (b == null) {
|
||||||
|
return "(null)";
|
||||||
|
}
|
||||||
|
StringBuffer sb = new StringBuffer(b.length * 3);
|
||||||
|
for (int i = 0; i < b.length; i++) {
|
||||||
|
int k = b[i] & 0xff;
|
||||||
|
if (i != 0) {
|
||||||
|
sb.append(':');
|
||||||
|
}
|
||||||
|
sb.append(hexDigits[k >>> 4]);
|
||||||
|
sb.append(hexDigits[k & 0xf]);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
798
src/main/java/com/sunyard/security/pkcs11/Secmod.java
Normal file
798
src/main/java/com/sunyard/security/pkcs11/Secmod.java
Normal file
@ -0,0 +1,798 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.KeyStore.*;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Secmod class defines the interface to the native NSS
|
||||||
|
* library and the configuration information it stores in its
|
||||||
|
* secmod.db file.
|
||||||
|
*
|
||||||
|
* <p>Example code:
|
||||||
|
* <pre>
|
||||||
|
* Secmod secmod = Secmod.getInstance();
|
||||||
|
* if (secmod.isInitialized() == false) {
|
||||||
|
* secmod.initialize("/home/myself/.mozilla", "/usr/sfw/lib/mozilla");
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Provider p = secmod.getModule(ModuleType.KEYSTORE).getProvider();
|
||||||
|
* KeyStore ks = KeyStore.getInstance("PKCS11", p);
|
||||||
|
* ks.load(null, password);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @since 1.6
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
*/
|
||||||
|
public final class Secmod {
|
||||||
|
|
||||||
|
private final static boolean DEBUG = false;
|
||||||
|
|
||||||
|
private final static Secmod INSTANCE;
|
||||||
|
|
||||||
|
static {
|
||||||
|
sun.security.pkcs11.wrapper.PKCS11.loadNative();
|
||||||
|
INSTANCE = new Secmod();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static String NSS_LIB_NAME = "nss3";
|
||||||
|
|
||||||
|
private final static String SOFTTOKEN_LIB_NAME = "softokn3";
|
||||||
|
|
||||||
|
private final static String TRUST_LIB_NAME = "nssckbi";
|
||||||
|
|
||||||
|
// Slot IDs - defined in j2secmod.h on the native side
|
||||||
|
// Values obtained from NSS's pkcs11i.h header
|
||||||
|
|
||||||
|
private final static int NETSCAPE_SLOT_ID = 0x1;
|
||||||
|
|
||||||
|
private final static int PRIVATE_KEY_SLOT_ID = 0x2;
|
||||||
|
|
||||||
|
private final static int FIPS_SLOT_ID = 0x3;
|
||||||
|
|
||||||
|
// handle to be passed to the native code, 0 means not initialized
|
||||||
|
private long nssHandle;
|
||||||
|
|
||||||
|
// whether this is a supported version of NSS
|
||||||
|
private boolean supported;
|
||||||
|
|
||||||
|
// list of the modules
|
||||||
|
private List<Module> modules;
|
||||||
|
|
||||||
|
private String configDir;
|
||||||
|
|
||||||
|
private String nssLibDir;
|
||||||
|
|
||||||
|
private Secmod() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the singleton Secmod instance.
|
||||||
|
*/
|
||||||
|
public static Secmod getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLoaded() {
|
||||||
|
if (nssHandle == 0) {
|
||||||
|
nssHandle = nssGetLibraryHandle(System.mapLibraryName(NSS_LIB_NAME));
|
||||||
|
if (nssHandle != 0) {
|
||||||
|
fetchVersions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (nssHandle != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchVersions() {
|
||||||
|
supported = nssVersionCheck(nssHandle, "3.7");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether this Secmod has been initialized. Returns true
|
||||||
|
* if NSS has been initialized using either the initialize() method
|
||||||
|
* or by directly calling the native NSS APIs. The latter may be
|
||||||
|
* the case if the current process contains components that use
|
||||||
|
* NSS directly.
|
||||||
|
*
|
||||||
|
* @throws IOException if an incompatible version of NSS
|
||||||
|
* has been loaded
|
||||||
|
*/
|
||||||
|
public synchronized boolean isInitialized() throws IOException {
|
||||||
|
// NSS does not allow us to check if it is initialized already
|
||||||
|
// assume that if it is loaded it is also initialized
|
||||||
|
if (isLoaded() == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (supported == false) {
|
||||||
|
throw new IOException
|
||||||
|
("An incompatible version of NSS is already loaded, "
|
||||||
|
+ "3.7 or later required");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getConfigDir() {
|
||||||
|
return configDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getLibDir() {
|
||||||
|
return nssLibDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize this Secmod.
|
||||||
|
*
|
||||||
|
* @param configDir the directory containing the NSS configuration
|
||||||
|
* files such as secmod.db
|
||||||
|
* @param nssLibDir the directory containing the NSS libraries
|
||||||
|
* (libnss3.so or nss3.dll) or null if the library is on
|
||||||
|
* the system default shared library path
|
||||||
|
*
|
||||||
|
* @throws IOException if NSS has already been initialized,
|
||||||
|
* the specified directories are invalid, or initialization
|
||||||
|
* fails for any other reason
|
||||||
|
*/
|
||||||
|
public void initialize(String configDir, String nssLibDir)
|
||||||
|
throws IOException {
|
||||||
|
initialize(DbMode.READ_WRITE, configDir, nssLibDir, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize(DbMode dbMode, String configDir, String nssLibDir)
|
||||||
|
throws IOException {
|
||||||
|
initialize(dbMode, configDir, nssLibDir, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void initialize(DbMode dbMode, String configDir,
|
||||||
|
String nssLibDir, boolean nssOptimizeSpace) throws IOException {
|
||||||
|
|
||||||
|
if (isInitialized()) {
|
||||||
|
throw new IOException("NSS is already initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dbMode == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
if ((dbMode != DbMode.NO_DB) && (configDir == null)) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
String platformLibName = System.mapLibraryName("nss3");
|
||||||
|
String platformPath;
|
||||||
|
if (nssLibDir == null) {
|
||||||
|
platformPath = platformLibName;
|
||||||
|
} else {
|
||||||
|
File base = new File(nssLibDir);
|
||||||
|
if (base.isDirectory() == false) {
|
||||||
|
throw new IOException("nssLibDir must be a directory:" + nssLibDir);
|
||||||
|
}
|
||||||
|
File platformFile = new File(base, platformLibName);
|
||||||
|
if (platformFile.isFile() == false) {
|
||||||
|
throw new FileNotFoundException(platformFile.getPath());
|
||||||
|
}
|
||||||
|
platformPath = platformFile.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configDir != null) {
|
||||||
|
String configDirPath = null;
|
||||||
|
String sqlPrefix = "sql:";
|
||||||
|
if (!configDir.startsWith(sqlPrefix)) {
|
||||||
|
configDirPath = configDir;
|
||||||
|
} else {
|
||||||
|
StringBuilder configDirPathSB = new StringBuilder(configDir);
|
||||||
|
configDirPath = configDirPathSB.substring(sqlPrefix.length());
|
||||||
|
}
|
||||||
|
File configBase = new File(configDirPath);
|
||||||
|
if (configBase.isDirectory() == false ) {
|
||||||
|
throw new IOException("configDir must be a directory: " + configDirPath);
|
||||||
|
}
|
||||||
|
if (!configDir.startsWith(sqlPrefix)) {
|
||||||
|
File secmodFile = new File(configBase, "secmod.db");
|
||||||
|
if (secmodFile.isFile() == false) {
|
||||||
|
throw new FileNotFoundException(secmodFile.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) System.out.println("lib: " + platformPath);
|
||||||
|
nssHandle = nssLoadLibrary(platformPath);
|
||||||
|
if (DEBUG) System.out.println("handle: " + nssHandle);
|
||||||
|
fetchVersions();
|
||||||
|
if (supported == false) {
|
||||||
|
throw new IOException
|
||||||
|
("The specified version of NSS is incompatible, "
|
||||||
|
+ "3.7 or later required");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) System.out.println("dir: " + configDir);
|
||||||
|
boolean initok = nssInitialize(dbMode.functionName, nssHandle,
|
||||||
|
configDir, nssOptimizeSpace);
|
||||||
|
if (DEBUG) System.out.println("init: " + initok);
|
||||||
|
if (initok == false) {
|
||||||
|
throw new IOException("NSS initialization failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.configDir = configDir;
|
||||||
|
this.nssLibDir = nssLibDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an immutable list of all available modules.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if this Secmod is misconfigured
|
||||||
|
* or not initialized
|
||||||
|
*/
|
||||||
|
public synchronized List<Module> getModules() {
|
||||||
|
try {
|
||||||
|
if (isInitialized() == false) {
|
||||||
|
throw new IllegalStateException("NSS not initialized");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// IOException if misconfigured
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
if (modules == null) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Module> modules = (List<Module>)nssGetModuleList(nssHandle,
|
||||||
|
nssLibDir);
|
||||||
|
this.modules = Collections.unmodifiableList(modules);
|
||||||
|
}
|
||||||
|
return modules;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] getDigest(X509Certificate cert, String algorithm) {
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance(algorithm);
|
||||||
|
return md.digest(cert.getEncoded());
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isTrusted(X509Certificate cert, TrustType trustType) {
|
||||||
|
Bytes bytes = new Bytes(getDigest(cert, "SHA-1"));
|
||||||
|
TrustAttributes attr = getModuleTrust(ModuleType.KEYSTORE, bytes);
|
||||||
|
if (attr == null) {
|
||||||
|
attr = getModuleTrust(ModuleType.FIPS, bytes);
|
||||||
|
if (attr == null) {
|
||||||
|
attr = getModuleTrust(ModuleType.TRUSTANCHOR, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (attr == null) ? false : attr.isTrusted(trustType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TrustAttributes getModuleTrust(ModuleType type, Bytes bytes) {
|
||||||
|
Module module = getModule(type);
|
||||||
|
TrustAttributes t = (module == null) ? null : module.getTrust(bytes);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants describing the different types of NSS modules.
|
||||||
|
* For this API, NSS modules are classified as either one
|
||||||
|
* of the internal modules delivered as part of NSS or
|
||||||
|
* as an external module provided by a 3rd party.
|
||||||
|
*/
|
||||||
|
public static enum ModuleType {
|
||||||
|
/**
|
||||||
|
* The NSS Softtoken crypto module. This is the first
|
||||||
|
* slot of the softtoken object.
|
||||||
|
* This module provides
|
||||||
|
* implementations for cryptographic algorithms but no KeyStore.
|
||||||
|
*/
|
||||||
|
CRYPTO,
|
||||||
|
/**
|
||||||
|
* The NSS Softtoken KeyStore module. This is the second
|
||||||
|
* slot of the softtoken object.
|
||||||
|
* This module provides
|
||||||
|
* implementations for cryptographic algorithms (after login)
|
||||||
|
* and the KeyStore.
|
||||||
|
*/
|
||||||
|
KEYSTORE,
|
||||||
|
/**
|
||||||
|
* The NSS Softtoken module in FIPS mode. Note that in FIPS mode the
|
||||||
|
* softtoken presents only one slot, not separate CRYPTO and KEYSTORE
|
||||||
|
* slots as in non-FIPS mode.
|
||||||
|
*/
|
||||||
|
FIPS,
|
||||||
|
/**
|
||||||
|
* The NSS builtin trust anchor module. This is the
|
||||||
|
* NSSCKBI object. It provides no crypto functions.
|
||||||
|
*/
|
||||||
|
TRUSTANCHOR,
|
||||||
|
/**
|
||||||
|
* An external module.
|
||||||
|
*/
|
||||||
|
EXTERNAL,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first module of the specified type. If no such
|
||||||
|
* module exists, this method returns null.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if this Secmod is misconfigured
|
||||||
|
* or not initialized
|
||||||
|
*/
|
||||||
|
public Module getModule(ModuleType type) {
|
||||||
|
for (Module module : getModules()) {
|
||||||
|
if (module.getType() == type) {
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final String TEMPLATE_EXTERNAL =
|
||||||
|
"library = %s\n"
|
||||||
|
+ "name = \"%s\"\n"
|
||||||
|
+ "slotListIndex = %d\n";
|
||||||
|
|
||||||
|
static final String TEMPLATE_TRUSTANCHOR =
|
||||||
|
"library = %s\n"
|
||||||
|
+ "name = \"NSS Trust Anchors\"\n"
|
||||||
|
+ "slotListIndex = 0\n"
|
||||||
|
+ "enabledMechanisms = { KeyStore }\n"
|
||||||
|
+ "nssUseSecmodTrust = true\n";
|
||||||
|
|
||||||
|
static final String TEMPLATE_CRYPTO =
|
||||||
|
"library = %s\n"
|
||||||
|
+ "name = \"NSS SoftToken Crypto\"\n"
|
||||||
|
+ "slotListIndex = 0\n"
|
||||||
|
+ "disabledMechanisms = { KeyStore }\n";
|
||||||
|
|
||||||
|
static final String TEMPLATE_KEYSTORE =
|
||||||
|
"library = %s\n"
|
||||||
|
+ "name = \"NSS SoftToken KeyStore\"\n"
|
||||||
|
+ "slotListIndex = 1\n"
|
||||||
|
+ "nssUseSecmodTrust = true\n";
|
||||||
|
|
||||||
|
static final String TEMPLATE_FIPS =
|
||||||
|
"library = %s\n"
|
||||||
|
+ "name = \"NSS FIPS SoftToken\"\n"
|
||||||
|
+ "slotListIndex = 0\n"
|
||||||
|
+ "nssUseSecmodTrust = true\n";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of one PKCS#11 slot in a PKCS#11 module.
|
||||||
|
*/
|
||||||
|
public static final class Module {
|
||||||
|
// path of the native library
|
||||||
|
final String libraryName;
|
||||||
|
// descriptive name used by NSS
|
||||||
|
final String commonName;
|
||||||
|
final int slot;
|
||||||
|
final ModuleType type;
|
||||||
|
|
||||||
|
private String config;
|
||||||
|
private SunPKCS11 provider;
|
||||||
|
|
||||||
|
// trust attributes. Used for the KEYSTORE and TRUSTANCHOR modules only
|
||||||
|
private Map<Bytes,TrustAttributes> trust;
|
||||||
|
|
||||||
|
Module(String libraryDir, String libraryName, String commonName,
|
||||||
|
int slotIndex, int slotId) {
|
||||||
|
ModuleType type;
|
||||||
|
|
||||||
|
if ((libraryName == null) || (libraryName.length() == 0)) {
|
||||||
|
// must be softtoken
|
||||||
|
libraryName = System.mapLibraryName(SOFTTOKEN_LIB_NAME);
|
||||||
|
if (slotId == NETSCAPE_SLOT_ID) {
|
||||||
|
type = ModuleType.CRYPTO;
|
||||||
|
} else if (slotId == PRIVATE_KEY_SLOT_ID) {
|
||||||
|
type = ModuleType.KEYSTORE;
|
||||||
|
} else if (slotId == FIPS_SLOT_ID) {
|
||||||
|
type = ModuleType.FIPS;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unexpected slot ID " + slotId +
|
||||||
|
" in the NSS Internal Module");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (libraryName.endsWith(System.mapLibraryName(TRUST_LIB_NAME))
|
||||||
|
|| commonName.equals("Builtin Roots Module")) {
|
||||||
|
type = ModuleType.TRUSTANCHOR;
|
||||||
|
} else {
|
||||||
|
type = ModuleType.EXTERNAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// On Ubuntu the libsoftokn3 library is located in a subdirectory
|
||||||
|
// of the system libraries directory. (Since Ubuntu 11.04.)
|
||||||
|
File libraryFile = new File(libraryDir, libraryName);
|
||||||
|
if (!libraryFile.isFile()) {
|
||||||
|
File failover = new File(libraryDir, "nss/" + libraryName);
|
||||||
|
if (failover.isFile()) {
|
||||||
|
libraryFile = failover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.libraryName = libraryFile.getPath();
|
||||||
|
this.commonName = commonName;
|
||||||
|
this.slot = slotIndex;
|
||||||
|
this.type = type;
|
||||||
|
initConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initConfiguration() {
|
||||||
|
switch (type) {
|
||||||
|
case EXTERNAL:
|
||||||
|
config = String.format(TEMPLATE_EXTERNAL, libraryName,
|
||||||
|
commonName + " " + slot, slot);
|
||||||
|
break;
|
||||||
|
case CRYPTO:
|
||||||
|
config = String.format(TEMPLATE_CRYPTO, libraryName);
|
||||||
|
break;
|
||||||
|
case KEYSTORE:
|
||||||
|
config = String.format(TEMPLATE_KEYSTORE, libraryName);
|
||||||
|
break;
|
||||||
|
case FIPS:
|
||||||
|
config = String.format(TEMPLATE_FIPS, libraryName);
|
||||||
|
break;
|
||||||
|
case TRUSTANCHOR:
|
||||||
|
config = String.format(TEMPLATE_TRUSTANCHOR, libraryName);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unknown module type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the configuration for this module. This is a string
|
||||||
|
* in the SunPKCS11 configuration format. It can be
|
||||||
|
* customized with additional options and then made
|
||||||
|
* current using the setConfiguration() method.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public synchronized String getConfiguration() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the configuration for this module.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if the associated provider
|
||||||
|
* instance has already been created.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public synchronized void setConfiguration(String config) {
|
||||||
|
if (provider != null) {
|
||||||
|
throw new IllegalStateException("Provider instance already created");
|
||||||
|
}
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the pathname of the native library that implements
|
||||||
|
* this module. For example, /usr/lib/libpkcs11.so.
|
||||||
|
*/
|
||||||
|
public String getLibraryName() {
|
||||||
|
return libraryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of this module.
|
||||||
|
*/
|
||||||
|
public ModuleType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the provider instance that is associated with this
|
||||||
|
* module. The first call to this method creates the provider
|
||||||
|
* instance.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public synchronized Provider getProvider() {
|
||||||
|
if (provider == null) {
|
||||||
|
provider = newProvider();
|
||||||
|
}
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized boolean hasInitializedProvider() {
|
||||||
|
return provider != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProvider(SunPKCS11 p) {
|
||||||
|
if (provider != null) {
|
||||||
|
throw new ProviderException("Secmod provider already initialized");
|
||||||
|
}
|
||||||
|
provider = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SunPKCS11 newProvider() {
|
||||||
|
try {
|
||||||
|
InputStream in = new ByteArrayInputStream(config.getBytes("UTF8"));
|
||||||
|
return new SunPKCS11(in);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// XXX
|
||||||
|
throw new ProviderException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void setTrust(Token token, X509Certificate cert) {
|
||||||
|
Bytes bytes = new Bytes(getDigest(cert, "SHA-1"));
|
||||||
|
TrustAttributes attr = getTrust(bytes);
|
||||||
|
if (attr == null) {
|
||||||
|
attr = new TrustAttributes(token, cert, bytes, CKT_NETSCAPE_TRUSTED_DELEGATOR);
|
||||||
|
trust.put(bytes, attr);
|
||||||
|
} else {
|
||||||
|
// does it already have the correct trust settings?
|
||||||
|
if (attr.isTrusted(TrustType.ALL) == false) {
|
||||||
|
// XXX not yet implemented
|
||||||
|
throw new ProviderException("Cannot change existing trust attributes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TrustAttributes getTrust(Bytes hash) {
|
||||||
|
if (trust == null) {
|
||||||
|
// If provider is not set, create a temporary provider to
|
||||||
|
// retrieve the trust information. This can happen if we need
|
||||||
|
// to get the trust information for the trustanchor module
|
||||||
|
// because we need to look for user customized settings in the
|
||||||
|
// keystore module (which may not have a provider created yet).
|
||||||
|
// Creating a temporary provider and then dropping it on the
|
||||||
|
// floor immediately is flawed, but it's the best we can do
|
||||||
|
// for now.
|
||||||
|
synchronized (this) {
|
||||||
|
SunPKCS11 p = provider;
|
||||||
|
if (p == null) {
|
||||||
|
p = newProvider();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
trust = Secmod.getTrust(p);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return trust.get(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return
|
||||||
|
commonName + " (" + type + ", " + libraryName + ", slot " + slot + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants representing NSS trust categories.
|
||||||
|
*/
|
||||||
|
public static enum TrustType {
|
||||||
|
/** Trusted for all purposes */
|
||||||
|
ALL,
|
||||||
|
/** Trusted for SSL client authentication */
|
||||||
|
CLIENT_AUTH,
|
||||||
|
/** Trusted for SSL server authentication */
|
||||||
|
SERVER_AUTH,
|
||||||
|
/** Trusted for code signing */
|
||||||
|
CODE_SIGNING,
|
||||||
|
/** Trusted for email protection */
|
||||||
|
EMAIL_PROTECTION,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum DbMode {
|
||||||
|
READ_WRITE("NSS_InitReadWrite"),
|
||||||
|
READ_ONLY ("NSS_Init"),
|
||||||
|
NO_DB ("NSS_NoDB_Init");
|
||||||
|
|
||||||
|
final String functionName;
|
||||||
|
DbMode(String functionName) {
|
||||||
|
this.functionName = functionName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A LoadStoreParameter for use with the NSS Softtoken or
|
||||||
|
* NSS TrustAnchor KeyStores.
|
||||||
|
* <p>
|
||||||
|
* It allows the set of trusted certificates that are returned by
|
||||||
|
* the KeyStore to be specified.
|
||||||
|
*/
|
||||||
|
public static final class KeyStoreLoadParameter implements LoadStoreParameter {
|
||||||
|
final TrustType trustType;
|
||||||
|
final ProtectionParameter protection;
|
||||||
|
public KeyStoreLoadParameter(TrustType trustType, char[] password) {
|
||||||
|
this(trustType, new PasswordProtection(password));
|
||||||
|
|
||||||
|
}
|
||||||
|
public KeyStoreLoadParameter(TrustType trustType, ProtectionParameter prot) {
|
||||||
|
if (trustType == null) {
|
||||||
|
throw new NullPointerException("trustType must not be null");
|
||||||
|
}
|
||||||
|
this.trustType = trustType;
|
||||||
|
this.protection = prot;
|
||||||
|
}
|
||||||
|
public ProtectionParameter getProtectionParameter() {
|
||||||
|
return protection;
|
||||||
|
}
|
||||||
|
public TrustType getTrustType() {
|
||||||
|
return trustType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TrustAttributes {
|
||||||
|
final long handle;
|
||||||
|
final long clientAuth, serverAuth, codeSigning, emailProtection;
|
||||||
|
final byte[] shaHash;
|
||||||
|
TrustAttributes(Token token, X509Certificate cert, Bytes bytes, long trustValue) {
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
// XXX use KeyStore TrustType settings to determine which
|
||||||
|
// attributes to set
|
||||||
|
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_TOKEN, true),
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH, trustValue),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING, trustValue),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION, trustValue),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH, trustValue),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH, bytes.b),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_MD5_HASH, getDigest(cert, "MD5")),
|
||||||
|
new CK_ATTRIBUTE(CKA_ISSUER, cert.getIssuerX500Principal().getEncoded()),
|
||||||
|
new CK_ATTRIBUTE(CKA_SERIAL_NUMBER, cert.getSerialNumber().toByteArray()),
|
||||||
|
// XXX per PKCS#11 spec, the serial number should be in ASN.1
|
||||||
|
};
|
||||||
|
handle = token.p11.C_CreateObject(session.id(), attrs);
|
||||||
|
shaHash = bytes.b;
|
||||||
|
clientAuth = trustValue;
|
||||||
|
serverAuth = trustValue;
|
||||||
|
codeSigning = trustValue;
|
||||||
|
emailProtection = trustValue;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Could not create trust object", e);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TrustAttributes(Token token, Session session, long handle)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
this.handle = handle;
|
||||||
|
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION),
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH),
|
||||||
|
};
|
||||||
|
|
||||||
|
token.p11.C_GetAttributeValue(session.id(), handle, attrs);
|
||||||
|
serverAuth = attrs[0].getLong();
|
||||||
|
codeSigning = attrs[1].getLong();
|
||||||
|
emailProtection = attrs[2].getLong();
|
||||||
|
shaHash = attrs[3].getByteArray();
|
||||||
|
|
||||||
|
attrs = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH),
|
||||||
|
};
|
||||||
|
long c;
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session.id(), handle, attrs);
|
||||||
|
c = attrs[0].getLong();
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// trust anchor module does not support this attribute
|
||||||
|
c = serverAuth;
|
||||||
|
}
|
||||||
|
clientAuth = c;
|
||||||
|
}
|
||||||
|
Bytes getHash() {
|
||||||
|
return new Bytes(shaHash);
|
||||||
|
}
|
||||||
|
boolean isTrusted(TrustType type) {
|
||||||
|
switch (type) {
|
||||||
|
case CLIENT_AUTH:
|
||||||
|
return isTrusted(clientAuth);
|
||||||
|
case SERVER_AUTH:
|
||||||
|
return isTrusted(serverAuth);
|
||||||
|
case CODE_SIGNING:
|
||||||
|
return isTrusted(codeSigning);
|
||||||
|
case EMAIL_PROTECTION:
|
||||||
|
return isTrusted(emailProtection);
|
||||||
|
case ALL:
|
||||||
|
return isTrusted(TrustType.CLIENT_AUTH)
|
||||||
|
&& isTrusted(TrustType.SERVER_AUTH)
|
||||||
|
&& isTrusted(TrustType.CODE_SIGNING)
|
||||||
|
&& isTrusted(TrustType.EMAIL_PROTECTION);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTrusted(long l) {
|
||||||
|
// XXX CKT_TRUSTED?
|
||||||
|
return (l == CKT_NETSCAPE_TRUSTED_DELEGATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Bytes {
|
||||||
|
final byte[] b;
|
||||||
|
Bytes(byte[] b) {
|
||||||
|
this.b = b;
|
||||||
|
}
|
||||||
|
public int hashCode() {
|
||||||
|
return Arrays.hashCode(b);
|
||||||
|
}
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o instanceof Bytes == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Bytes other = (Bytes)o;
|
||||||
|
return Arrays.equals(this.b, other.b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Bytes,TrustAttributes> getTrust(SunPKCS11 provider)
|
||||||
|
throws PKCS11Exception {
|
||||||
|
Map<Bytes,TrustAttributes> trustMap = new HashMap<Bytes,TrustAttributes>();
|
||||||
|
Token token = provider.getToken();
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getOpSession();
|
||||||
|
int MAX_NUM = 8192;
|
||||||
|
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST),
|
||||||
|
};
|
||||||
|
token.p11.C_FindObjectsInit(session.id(), attrs);
|
||||||
|
long[] handles = token.p11.C_FindObjects(session.id(), MAX_NUM);
|
||||||
|
token.p11.C_FindObjectsFinal(session.id());
|
||||||
|
if (DEBUG) System.out.println("handles: " + handles.length);
|
||||||
|
|
||||||
|
for (long handle : handles) {
|
||||||
|
try {
|
||||||
|
TrustAttributes trust = new TrustAttributes(token, session, handle);
|
||||||
|
trustMap.put(trust.getHash(), trust);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// skip put on pkcs11 error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
return trustMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native long nssGetLibraryHandle(String libraryName);
|
||||||
|
|
||||||
|
private static native long nssLoadLibrary(String name) throws IOException;
|
||||||
|
|
||||||
|
private static native boolean nssVersionCheck(long handle, String minVersion);
|
||||||
|
|
||||||
|
private static native boolean nssInitialize(String functionName, long handle, String configDir, boolean nssOptimizeSpace);
|
||||||
|
|
||||||
|
private static native Object nssGetModuleList(long handle, String libDir);
|
||||||
|
|
||||||
|
}
|
189
src/main/java/com/sunyard/security/pkcs11/Session.java
Normal file
189
src/main/java/com/sunyard/security/pkcs11/Session.java
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.lang.ref.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A session object. Sessions are obtained via the SessionManager,
|
||||||
|
* see there for details. Most code will only ever need one method in
|
||||||
|
* this class, the id() method to obtain the session id.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class Session implements Comparable<Session> {
|
||||||
|
|
||||||
|
// time after which to close idle sessions, in milliseconds (3 minutes)
|
||||||
|
private final static long MAX_IDLE_TIME = 3 * 60 * 1000;
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
final Token token;
|
||||||
|
|
||||||
|
// session id
|
||||||
|
private final long id;
|
||||||
|
|
||||||
|
// number of objects created within this session
|
||||||
|
private final AtomicInteger createdObjects;
|
||||||
|
|
||||||
|
// time this session was last used
|
||||||
|
// not synchronized/volatile for performance, so may be unreliable
|
||||||
|
// this could lead to idle sessions being closed early, but that is harmless
|
||||||
|
private long lastAccess;
|
||||||
|
|
||||||
|
private final SessionRef sessionRef;
|
||||||
|
|
||||||
|
Session(Token token, long id) {
|
||||||
|
this.token = token;
|
||||||
|
this.id = id;
|
||||||
|
createdObjects = new AtomicInteger();
|
||||||
|
id();
|
||||||
|
sessionRef = new SessionRef(this, id, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(Session other) {
|
||||||
|
if (this.lastAccess == other.lastAccess) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return (this.lastAccess < other.lastAccess) ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isLive(long currentTime) {
|
||||||
|
return currentTime - lastAccess < MAX_IDLE_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
long idInternal() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
long id() {
|
||||||
|
if (token.isPresent(this.id) == false) {
|
||||||
|
throw new ProviderException("Token has been removed");
|
||||||
|
}
|
||||||
|
lastAccess = System.currentTimeMillis();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addObject() {
|
||||||
|
int n = createdObjects.incrementAndGet();
|
||||||
|
// XXX update statistics in session manager if n == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeObject() {
|
||||||
|
int n = createdObjects.decrementAndGet();
|
||||||
|
if (n == 0) {
|
||||||
|
token.sessionManager.demoteObjSession(this);
|
||||||
|
} else if (n < 0) {
|
||||||
|
throw new ProviderException("Internal error: objects created " + n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasObjects() {
|
||||||
|
return createdObjects.get() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
if (hasObjects()) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"Internal error: close session with active objects");
|
||||||
|
}
|
||||||
|
sessionRef.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: Use PhantomReference here and not WeakReference
|
||||||
|
* otherwise the sessions maybe closed before other objects
|
||||||
|
* which are still being finalized.
|
||||||
|
*/
|
||||||
|
final class SessionRef extends PhantomReference<Session>
|
||||||
|
implements Comparable<SessionRef> {
|
||||||
|
|
||||||
|
private static ReferenceQueue<Session> refQueue =
|
||||||
|
new ReferenceQueue<Session>();
|
||||||
|
|
||||||
|
private static Set<SessionRef> refList =
|
||||||
|
Collections.synchronizedSortedSet(new TreeSet<SessionRef>());
|
||||||
|
|
||||||
|
static ReferenceQueue<Session> referenceQueue() {
|
||||||
|
return refQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int totalCount() {
|
||||||
|
return refList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drainRefQueueBounded() {
|
||||||
|
while (true) {
|
||||||
|
SessionRef next = (SessionRef) refQueue.poll();
|
||||||
|
if (next == null) break;
|
||||||
|
next.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle to the native session
|
||||||
|
private long id;
|
||||||
|
private Token token;
|
||||||
|
|
||||||
|
SessionRef(Session session, long id, Token token) {
|
||||||
|
super(session, refQueue);
|
||||||
|
this.id = id;
|
||||||
|
this.token = token;
|
||||||
|
refList.add(this);
|
||||||
|
// TBD: run at some interval and not every time?
|
||||||
|
drainRefQueueBounded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
refList.remove(this);
|
||||||
|
try {
|
||||||
|
if (token.isPresent(id)) {
|
||||||
|
token.p11.C_CloseSession(id);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e1) {
|
||||||
|
// ignore
|
||||||
|
} catch (ProviderException e2) {
|
||||||
|
// ignore
|
||||||
|
} finally {
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(SessionRef other) {
|
||||||
|
if (this.id == other.id) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return (this.id < other.id) ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
295
src/main/java/com/sunyard/security/pkcs11/SessionManager.java
Normal file
295
src/main/java/com/sunyard/security/pkcs11/SessionManager.java
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import java.security.ProviderException;
|
||||||
|
|
||||||
|
import sun.security.util.Debug;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session manager. There is one session manager object per PKCS#11
|
||||||
|
* provider. It allows code to checkout a session, release it
|
||||||
|
* back to the pool, or force it to be closed.
|
||||||
|
*
|
||||||
|
* The session manager pools sessions to minimize the number of
|
||||||
|
* C_OpenSession() and C_CloseSession() that have to be made. It
|
||||||
|
* maintains two pools: one for "object" sessions and one for
|
||||||
|
* "operation" sessions.
|
||||||
|
*
|
||||||
|
* The reason for this separation is how PKCS#11 deals with session objects.
|
||||||
|
* It defines that when a session is closed, all objects created within
|
||||||
|
* that session are destroyed. In other words, we may never close a session
|
||||||
|
* while a Key created it in is still in use. We would like to keep the
|
||||||
|
* number of such sessions low. Note that we occasionally want to explicitly
|
||||||
|
* close a session, see P11Signature.
|
||||||
|
*
|
||||||
|
* NOTE that sessions obtained from this class SHOULD be returned using
|
||||||
|
* either releaseSession() or closeSession() using a finally block when
|
||||||
|
* not needed anymore. Otherwise, they will be left for cleanup via the
|
||||||
|
* PhantomReference mechanism when GC kicks in, but it's best not to rely
|
||||||
|
* on that since GC may not run timely enough since the native PKCS11 library
|
||||||
|
* is also consuming memory.
|
||||||
|
*
|
||||||
|
* Note that sessions are automatically closed when they are not used for a
|
||||||
|
* period of time, see Session.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class SessionManager {
|
||||||
|
|
||||||
|
private final static int DEFAULT_MAX_SESSIONS = 32;
|
||||||
|
|
||||||
|
private final static Debug debug = Debug.getInstance("pkcs11");
|
||||||
|
|
||||||
|
// token instance
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
// maximum number of sessions to open with this token
|
||||||
|
private final int maxSessions;
|
||||||
|
|
||||||
|
// total number of active sessions
|
||||||
|
private AtomicInteger activeSessions = new AtomicInteger();
|
||||||
|
|
||||||
|
// pool of available object sessions
|
||||||
|
private final Pool objSessions;
|
||||||
|
|
||||||
|
// pool of available operation sessions
|
||||||
|
private final Pool opSessions;
|
||||||
|
|
||||||
|
// maximum number of active sessions during this invocation, for debugging
|
||||||
|
private int maxActiveSessions;
|
||||||
|
private Object maxActiveSessionsLock;
|
||||||
|
|
||||||
|
// flags to use in the C_OpenSession() call
|
||||||
|
private final long openSessionFlags;
|
||||||
|
|
||||||
|
SessionManager(Token token) {
|
||||||
|
long n;
|
||||||
|
if (token.isWriteProtected()) {
|
||||||
|
openSessionFlags = CKF_SERIAL_SESSION;
|
||||||
|
n = token.tokenInfo.ulMaxSessionCount;
|
||||||
|
} else {
|
||||||
|
openSessionFlags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
|
||||||
|
n = token.tokenInfo.ulMaxRwSessionCount;
|
||||||
|
}
|
||||||
|
if (n == CK_EFFECTIVELY_INFINITE) {
|
||||||
|
n = Integer.MAX_VALUE;
|
||||||
|
} else if ((n == CK_UNAVAILABLE_INFORMATION) || (n < 0)) {
|
||||||
|
// choose an arbitrary concrete value
|
||||||
|
n = DEFAULT_MAX_SESSIONS;
|
||||||
|
}
|
||||||
|
maxSessions = (int)Math.min(n, Integer.MAX_VALUE);
|
||||||
|
this.token = token;
|
||||||
|
this.objSessions = new Pool(this);
|
||||||
|
this.opSessions = new Pool(this);
|
||||||
|
if (debug != null) {
|
||||||
|
maxActiveSessionsLock = new Object();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns whether only a fairly low number of sessions are
|
||||||
|
// supported by this token.
|
||||||
|
boolean lowMaxSessions() {
|
||||||
|
return (maxSessions <= DEFAULT_MAX_SESSIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session getObjSession() throws PKCS11Exception {
|
||||||
|
Session session = objSessions.poll();
|
||||||
|
if (session != null) {
|
||||||
|
return ensureValid(session);
|
||||||
|
}
|
||||||
|
session = opSessions.poll();
|
||||||
|
if (session != null) {
|
||||||
|
return ensureValid(session);
|
||||||
|
}
|
||||||
|
session = openSession();
|
||||||
|
return ensureValid(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session getOpSession() throws PKCS11Exception {
|
||||||
|
Session session = opSessions.poll();
|
||||||
|
if (session != null) {
|
||||||
|
return ensureValid(session);
|
||||||
|
}
|
||||||
|
// create a new session rather than re-using an obj session
|
||||||
|
// that avoids potential expensive cancels() for Signatures & RSACipher
|
||||||
|
if (maxSessions == Integer.MAX_VALUE ||
|
||||||
|
activeSessions.get() < maxSessions) {
|
||||||
|
session = openSession();
|
||||||
|
return ensureValid(session);
|
||||||
|
}
|
||||||
|
session = objSessions.poll();
|
||||||
|
if (session != null) {
|
||||||
|
return ensureValid(session);
|
||||||
|
}
|
||||||
|
throw new ProviderException("Could not obtain session");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Session ensureValid(Session session) {
|
||||||
|
session.id();
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
Session killSession(Session session) {
|
||||||
|
if ((session == null) || (token.isValid() == false)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (debug != null) {
|
||||||
|
String location = new Exception().getStackTrace()[2].toString();
|
||||||
|
System.out.println("Killing session (" + location + ") active: "
|
||||||
|
+ activeSessions.get());
|
||||||
|
}
|
||||||
|
closeSession(session);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Session releaseSession(Session session) {
|
||||||
|
if ((session == null) || (token.isValid() == false)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.hasObjects()) {
|
||||||
|
objSessions.release(session);
|
||||||
|
} else {
|
||||||
|
opSessions.release(session);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void demoteObjSession(Session session) {
|
||||||
|
if (token.isValid() == false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (debug != null) {
|
||||||
|
System.out.println("Demoting session, active: " +
|
||||||
|
activeSessions.get());
|
||||||
|
}
|
||||||
|
boolean present = objSessions.remove(session);
|
||||||
|
if (present == false) {
|
||||||
|
// session is currently in use
|
||||||
|
// will be added to correct pool on release, nothing to do now
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Objects could have been added to this session by other thread between
|
||||||
|
// check in Session.removeObject method and objSessions.remove call
|
||||||
|
// higher. Therefore releaseSession method, which performs additional
|
||||||
|
// check for objects, is used here to avoid placing this session
|
||||||
|
// in wrong pool due to race condition.
|
||||||
|
releaseSession(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Session openSession() throws PKCS11Exception {
|
||||||
|
if ((maxSessions != Integer.MAX_VALUE) &&
|
||||||
|
(activeSessions.get() >= maxSessions)) {
|
||||||
|
throw new ProviderException("No more sessions available");
|
||||||
|
}
|
||||||
|
|
||||||
|
long id = token.p11.C_OpenSession
|
||||||
|
(token.provider.slotID, openSessionFlags, null, null);
|
||||||
|
Session session = new Session(token, id);
|
||||||
|
activeSessions.incrementAndGet();
|
||||||
|
if (debug != null) {
|
||||||
|
synchronized(maxActiveSessionsLock) {
|
||||||
|
if (activeSessions.get() > maxActiveSessions) {
|
||||||
|
maxActiveSessions = activeSessions.get();
|
||||||
|
if (maxActiveSessions % 10 == 0) {
|
||||||
|
System.out.println("Open sessions: " + maxActiveSessions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeSession(Session session) {
|
||||||
|
session.close();
|
||||||
|
activeSessions.decrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Pool {
|
||||||
|
|
||||||
|
private final SessionManager mgr;
|
||||||
|
|
||||||
|
private final ConcurrentLinkedDeque<Session> pool;
|
||||||
|
|
||||||
|
Pool(SessionManager mgr) {
|
||||||
|
this.mgr = mgr;
|
||||||
|
pool = new ConcurrentLinkedDeque<Session>();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean remove(Session session) {
|
||||||
|
return pool.remove(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session poll() {
|
||||||
|
return pool.pollLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
void release(Session session) {
|
||||||
|
pool.offer(session);
|
||||||
|
if (session.hasObjects()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = pool.size();
|
||||||
|
if (n < 5) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Session oldestSession;
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
int i = 0;
|
||||||
|
// Check if the session head is too old and continue through queue
|
||||||
|
// until only one is left.
|
||||||
|
do {
|
||||||
|
oldestSession = pool.peek();
|
||||||
|
if (oldestSession == null || oldestSession.isLive(time) ||
|
||||||
|
!pool.remove(oldestSession)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
mgr.closeSession(oldestSession);
|
||||||
|
} while ((n - i) > 1);
|
||||||
|
|
||||||
|
if (debug != null) {
|
||||||
|
System.out.println("Closing " + i + " idle sessions, active: "
|
||||||
|
+ mgr.activeSessions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1550
src/main/java/com/sunyard/security/pkcs11/SunPKCS11.java
Normal file
1550
src/main/java/com/sunyard/security/pkcs11/SunPKCS11.java
Normal file
File diff suppressed because it is too large
Load Diff
241
src/main/java/com/sunyard/security/pkcs11/TemplateManager.java
Normal file
241
src/main/java/com/sunyard/security/pkcs11/TemplateManager.java
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TemplateManager class.
|
||||||
|
*
|
||||||
|
* Not all PKCS#11 tokens are created equal. One token may require that one
|
||||||
|
* value is specified when creating a certain type of object. Another token
|
||||||
|
* may require a different value. Yet another token may only work if the
|
||||||
|
* attribute is not specified at all.
|
||||||
|
*
|
||||||
|
* In order to allow an application to work unmodified with all those
|
||||||
|
* different tokens, the SunPKCS11 provider makes the attributes that are
|
||||||
|
* specified and their value configurable. Hence, only the SunPKCS11
|
||||||
|
* configuration file has to be tweaked at deployment time to allow all
|
||||||
|
* existing applications to be used.
|
||||||
|
*
|
||||||
|
* The template manager is responsible for reading the attribute configuration
|
||||||
|
* information and to make it available to the various internal components
|
||||||
|
* of the SunPKCS11 provider.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
final class TemplateManager {
|
||||||
|
|
||||||
|
private final static boolean DEBUG = false;
|
||||||
|
|
||||||
|
// constant for any operation (either O_IMPORT or O_GENERATE)
|
||||||
|
final static String O_ANY = "*";
|
||||||
|
// constant for operation create ("importing" existing key material)
|
||||||
|
final static String O_IMPORT = "import";
|
||||||
|
// constant for operation generate (generating new key material)
|
||||||
|
final static String O_GENERATE = "generate";
|
||||||
|
|
||||||
|
private static class KeyAndTemplate {
|
||||||
|
final TemplateKey key;
|
||||||
|
final Template template;
|
||||||
|
|
||||||
|
KeyAndTemplate(TemplateKey key, Template template) {
|
||||||
|
this.key = key;
|
||||||
|
this.template = template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// primitive templates contains the individual template configuration
|
||||||
|
// entries from the configuration file
|
||||||
|
private final List<KeyAndTemplate> primitiveTemplates;
|
||||||
|
|
||||||
|
// composite templates is a cache of the exact configuration template for
|
||||||
|
// each specific TemplateKey (no wildcards). the entries are created
|
||||||
|
// on demand during first use by compositing all applicable
|
||||||
|
// primitive template entries. the result is then stored in this map
|
||||||
|
// for performance
|
||||||
|
private final Map<TemplateKey,Template> compositeTemplates;
|
||||||
|
|
||||||
|
TemplateManager() {
|
||||||
|
primitiveTemplates = new ArrayList<KeyAndTemplate>();
|
||||||
|
compositeTemplates = new ConcurrentHashMap<TemplateKey,Template>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a template. Called by Config.
|
||||||
|
void addTemplate(String op, long objectClass, long keyAlgorithm,
|
||||||
|
CK_ATTRIBUTE[] attrs) {
|
||||||
|
TemplateKey key = new TemplateKey(op, objectClass, keyAlgorithm);
|
||||||
|
Template template = new Template(attrs);
|
||||||
|
if (DEBUG) {
|
||||||
|
System.out.println("Adding " + key + " -> " + template);
|
||||||
|
}
|
||||||
|
primitiveTemplates.add(new KeyAndTemplate(key, template));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Template getTemplate(TemplateKey key) {
|
||||||
|
Template template = compositeTemplates.get(key);
|
||||||
|
if (template == null) {
|
||||||
|
template = buildCompositeTemplate(key);
|
||||||
|
compositeTemplates.put(key, template);
|
||||||
|
}
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the attributes for the requested op and combine them with attrs.
|
||||||
|
// This is the method called by the implementation to obtain the
|
||||||
|
// attributes.
|
||||||
|
CK_ATTRIBUTE[] getAttributes(String op, long type, long alg,
|
||||||
|
CK_ATTRIBUTE[] attrs) {
|
||||||
|
TemplateKey key = new TemplateKey(op, type, alg);
|
||||||
|
Template template = getTemplate(key);
|
||||||
|
CK_ATTRIBUTE[] newAttrs = template.getAttributes(attrs);
|
||||||
|
if (DEBUG) {
|
||||||
|
System.out.println(key + " -> " + Arrays.asList(newAttrs));
|
||||||
|
}
|
||||||
|
return newAttrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build a composite template for the given key
|
||||||
|
private Template buildCompositeTemplate(TemplateKey key) {
|
||||||
|
Template comp = new Template();
|
||||||
|
// iterate through primitive templates and add all that apply
|
||||||
|
for (KeyAndTemplate entry : primitiveTemplates) {
|
||||||
|
if (entry.key.appliesTo(key)) {
|
||||||
|
comp.add(entry.template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nested class representing a template identifier.
|
||||||
|
*/
|
||||||
|
private static final class TemplateKey {
|
||||||
|
final String operation;
|
||||||
|
final long keyType;
|
||||||
|
final long keyAlgorithm;
|
||||||
|
TemplateKey(String operation, long keyType, long keyAlgorithm) {
|
||||||
|
this.operation = operation;
|
||||||
|
this.keyType = keyType;
|
||||||
|
this.keyAlgorithm = keyAlgorithm;
|
||||||
|
}
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj instanceof TemplateKey == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TemplateKey other = (TemplateKey)obj;
|
||||||
|
boolean match = this.operation.equals(other.operation)
|
||||||
|
&& (this.keyType == other.keyType)
|
||||||
|
&& (this.keyAlgorithm == other.keyAlgorithm);
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
public int hashCode() {
|
||||||
|
return operation.hashCode() + (int)keyType + (int)keyAlgorithm;
|
||||||
|
}
|
||||||
|
boolean appliesTo(TemplateKey key) {
|
||||||
|
if (operation.equals(O_ANY) || operation.equals(key.operation)) {
|
||||||
|
if ((keyType == PCKO_ANY) || (keyType == key.keyType)) {
|
||||||
|
if ((keyAlgorithm == PCKK_ANY)
|
||||||
|
|| (keyAlgorithm == key.keyAlgorithm)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return "(" + operation + ","
|
||||||
|
+ Functions.getObjectClassName(keyType)
|
||||||
|
+ "," + Functions.getKeyName(keyAlgorithm) + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nested class representing template attributes.
|
||||||
|
*/
|
||||||
|
private static final class Template {
|
||||||
|
|
||||||
|
private final static CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
|
||||||
|
|
||||||
|
private CK_ATTRIBUTE[] attributes;
|
||||||
|
|
||||||
|
Template() {
|
||||||
|
attributes = A0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Template(CK_ATTRIBUTE[] attributes) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(Template template) {
|
||||||
|
attributes = getAttributes(template.attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_ATTRIBUTE[] getAttributes(CK_ATTRIBUTE[] attrs) {
|
||||||
|
return combine(attributes, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combine two sets of attributes. The second set has precedence
|
||||||
|
* over the first and overrides its settings.
|
||||||
|
*/
|
||||||
|
private static CK_ATTRIBUTE[] combine(CK_ATTRIBUTE[] attrs1,
|
||||||
|
CK_ATTRIBUTE[] attrs2) {
|
||||||
|
List<CK_ATTRIBUTE> attrs = new ArrayList<CK_ATTRIBUTE>();
|
||||||
|
for (CK_ATTRIBUTE attr : attrs1) {
|
||||||
|
if (attr.pValue != null) {
|
||||||
|
attrs.add(attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (CK_ATTRIBUTE attr2 : attrs2) {
|
||||||
|
long type = attr2.type;
|
||||||
|
for (CK_ATTRIBUTE attr1 : attrs1) {
|
||||||
|
if (attr1.type == type) {
|
||||||
|
attrs.remove(attr1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attr2.pValue != null) {
|
||||||
|
attrs.add(attr2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attrs.toArray(A0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return Arrays.asList(attributes).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
465
src/main/java/com/sunyard/security/pkcs11/Token.java
Normal file
465
src/main/java/com/sunyard/security/pkcs11/Token.java
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.ref.*;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import javax.security.auth.login.LoginException;
|
||||||
|
|
||||||
|
import sun.security.jca.JCAUtil;
|
||||||
|
|
||||||
|
import com.sunyard.security.pkcs11.wrapper.*;
|
||||||
|
import static com.sunyard.security.pkcs11.TemplateManager.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PKCS#11 token.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
class Token implements Serializable {
|
||||||
|
|
||||||
|
// need to be serializable to allow SecureRandom to be serialized
|
||||||
|
private static final long serialVersionUID = 2541527649100571747L;
|
||||||
|
|
||||||
|
// how often to check if the token is still present (in ms)
|
||||||
|
// this is different from checking if a token has been inserted,
|
||||||
|
// that is done in SunPKCS11. Currently 50 ms.
|
||||||
|
private final static long CHECK_INTERVAL = 50;
|
||||||
|
|
||||||
|
final SunPKCS11 provider;
|
||||||
|
|
||||||
|
final PKCS11 p11;
|
||||||
|
|
||||||
|
final Config config;
|
||||||
|
|
||||||
|
final CK_TOKEN_INFO tokenInfo;
|
||||||
|
|
||||||
|
// session manager to pool sessions
|
||||||
|
final SessionManager sessionManager;
|
||||||
|
|
||||||
|
// template manager to customize the attributes used when creating objects
|
||||||
|
private final TemplateManager templateManager;
|
||||||
|
|
||||||
|
// flag indicating whether we need to explicitly cancel operations
|
||||||
|
// we started on the token. If false, we assume operations are
|
||||||
|
// automatically cancelled once we start another one
|
||||||
|
final boolean explicitCancel;
|
||||||
|
|
||||||
|
// translation cache for secret keys
|
||||||
|
final KeyCache secretCache;
|
||||||
|
|
||||||
|
// translation cache for asymmetric keys (public and private)
|
||||||
|
final KeyCache privateCache;
|
||||||
|
|
||||||
|
// cached instances of the various key factories, initialized on demand
|
||||||
|
private volatile P11KeyFactory rsaFactory, dsaFactory, dhFactory, ecFactory;
|
||||||
|
|
||||||
|
// table which maps mechanisms to the corresponding cached
|
||||||
|
// MechanismInfo objects
|
||||||
|
private final Map<Long, CK_MECHANISM_INFO> mechInfoMap;
|
||||||
|
|
||||||
|
// single SecureRandomSpi instance we use per token
|
||||||
|
// initialized on demand (if supported)
|
||||||
|
private volatile P11SecureRandom secureRandom;
|
||||||
|
|
||||||
|
// single KeyStoreSpi instance we use per provider
|
||||||
|
// initialized on demand
|
||||||
|
private volatile P11KeyStore keyStore;
|
||||||
|
|
||||||
|
// whether this token is a removable token
|
||||||
|
private final boolean removable;
|
||||||
|
|
||||||
|
// for removable tokens: whether this token is valid or has been removed
|
||||||
|
private volatile boolean valid;
|
||||||
|
|
||||||
|
// for removable tokens: time last checked for token presence
|
||||||
|
private long lastPresentCheck;
|
||||||
|
|
||||||
|
// unique token id, used for serialization only
|
||||||
|
private byte[] tokenId;
|
||||||
|
|
||||||
|
// flag indicating whether the token is write protected
|
||||||
|
private boolean writeProtected;
|
||||||
|
|
||||||
|
// flag indicating whether we are logged in
|
||||||
|
private volatile boolean loggedIn;
|
||||||
|
|
||||||
|
// time we last checked login status
|
||||||
|
private long lastLoginCheck;
|
||||||
|
|
||||||
|
// mutex for token-present-check
|
||||||
|
private final static Object CHECK_LOCK = new Object();
|
||||||
|
|
||||||
|
// object for indicating unsupported mechanism in 'mechInfoMap'
|
||||||
|
private final static CK_MECHANISM_INFO INVALID_MECH =
|
||||||
|
new CK_MECHANISM_INFO(0, 0, 0);
|
||||||
|
|
||||||
|
// flag indicating whether the token supports raw secret key material import
|
||||||
|
private Boolean supportsRawSecretKeyImport;
|
||||||
|
|
||||||
|
Token(SunPKCS11 provider) throws PKCS11Exception {
|
||||||
|
this.provider = provider;
|
||||||
|
this.removable = provider.removable;
|
||||||
|
this.valid = true;
|
||||||
|
p11 = provider.p11;
|
||||||
|
config = provider.config;
|
||||||
|
tokenInfo = p11.C_GetTokenInfo(provider.slotID);
|
||||||
|
writeProtected = (tokenInfo.flags & CKF_WRITE_PROTECTED) != 0;
|
||||||
|
// create session manager and open a test session
|
||||||
|
SessionManager sessionManager;
|
||||||
|
try {
|
||||||
|
sessionManager = new SessionManager(this);
|
||||||
|
Session s = sessionManager.getOpSession();
|
||||||
|
sessionManager.releaseSession(s);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
if (writeProtected) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
// token might not permit RW sessions even though
|
||||||
|
// CKF_WRITE_PROTECTED is not set
|
||||||
|
writeProtected = true;
|
||||||
|
sessionManager = new SessionManager(this);
|
||||||
|
Session s = sessionManager.getOpSession();
|
||||||
|
sessionManager.releaseSession(s);
|
||||||
|
}
|
||||||
|
this.sessionManager = sessionManager;
|
||||||
|
secretCache = new KeyCache();
|
||||||
|
privateCache = new KeyCache();
|
||||||
|
templateManager = config.getTemplateManager();
|
||||||
|
explicitCancel = config.getExplicitCancel();
|
||||||
|
mechInfoMap =
|
||||||
|
new ConcurrentHashMap<Long, CK_MECHANISM_INFO>(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isWriteProtected() {
|
||||||
|
return writeProtected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return whether the token supports raw secret key material import
|
||||||
|
boolean supportsRawSecretKeyImport() {
|
||||||
|
if (supportsRawSecretKeyImport == null) {
|
||||||
|
SecureRandom random = JCAUtil.getSecureRandom();
|
||||||
|
byte[] encoded = new byte[48];
|
||||||
|
random.nextBytes(encoded);
|
||||||
|
|
||||||
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[3];
|
||||||
|
attributes[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY);
|
||||||
|
attributes[1] = new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_GENERIC_SECRET);
|
||||||
|
attributes[2] = new CK_ATTRIBUTE(CKA_VALUE, encoded);
|
||||||
|
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
attributes = getAttributes(O_IMPORT,
|
||||||
|
CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
|
||||||
|
session = getObjSession();
|
||||||
|
long keyID = p11.C_CreateObject(session.id(), attributes);
|
||||||
|
|
||||||
|
supportsRawSecretKeyImport = Boolean.TRUE;
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
supportsRawSecretKeyImport = Boolean.FALSE;
|
||||||
|
} finally {
|
||||||
|
releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return supportsRawSecretKeyImport;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return whether we are logged in
|
||||||
|
// uses cached result if current. session is optional and may be null
|
||||||
|
boolean isLoggedIn(Session session) throws PKCS11Exception {
|
||||||
|
// volatile load first
|
||||||
|
boolean loggedIn = this.loggedIn;
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
if (time - lastLoginCheck > CHECK_INTERVAL) {
|
||||||
|
loggedIn = isLoggedInNow(session);
|
||||||
|
lastLoginCheck = time;
|
||||||
|
}
|
||||||
|
return loggedIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return whether we are logged in now
|
||||||
|
// does not use cache
|
||||||
|
boolean isLoggedInNow(Session session) throws PKCS11Exception {
|
||||||
|
boolean allocSession = (session == null);
|
||||||
|
try {
|
||||||
|
if (allocSession) {
|
||||||
|
session = getOpSession();
|
||||||
|
}
|
||||||
|
CK_SESSION_INFO info = p11.C_GetSessionInfo(session.id());
|
||||||
|
boolean loggedIn = (info.state == CKS_RO_USER_FUNCTIONS) ||
|
||||||
|
(info.state == CKS_RW_USER_FUNCTIONS);
|
||||||
|
this.loggedIn = loggedIn;
|
||||||
|
return loggedIn;
|
||||||
|
} finally {
|
||||||
|
if (allocSession) {
|
||||||
|
releaseSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that we are logged in
|
||||||
|
// call provider.login() if not
|
||||||
|
void ensureLoggedIn(Session session) throws PKCS11Exception, LoginException {
|
||||||
|
if (isLoggedIn(session) == false) {
|
||||||
|
provider.login(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return whether this token object is valid (i.e. token not removed)
|
||||||
|
// returns value from last check, does not perform new check
|
||||||
|
boolean isValid() {
|
||||||
|
if (removable == false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensureValid() {
|
||||||
|
if (isValid() == false) {
|
||||||
|
throw new ProviderException("Token has been removed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return whether a token is present (i.e. token not removed)
|
||||||
|
// returns cached value if current, otherwise performs new check
|
||||||
|
boolean isPresent(long sessionID) {
|
||||||
|
if (removable == false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (valid == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
if ((time - lastPresentCheck) >= CHECK_INTERVAL) {
|
||||||
|
synchronized (CHECK_LOCK) {
|
||||||
|
if ((time - lastPresentCheck) >= CHECK_INTERVAL) {
|
||||||
|
boolean ok = false;
|
||||||
|
try {
|
||||||
|
// check if token still present
|
||||||
|
CK_SLOT_INFO slotInfo =
|
||||||
|
provider.p11.C_GetSlotInfo(provider.slotID);
|
||||||
|
if ((slotInfo.flags & CKF_TOKEN_PRESENT) != 0) {
|
||||||
|
// if the token has been removed and re-inserted,
|
||||||
|
// the token should return an error
|
||||||
|
CK_SESSION_INFO sessInfo =
|
||||||
|
provider.p11.C_GetSessionInfo
|
||||||
|
(sessionID);
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
valid = ok;
|
||||||
|
lastPresentCheck = System.currentTimeMillis();
|
||||||
|
if (ok == false) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
valid = false;
|
||||||
|
provider.uninitToken(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session getObjSession() throws PKCS11Exception {
|
||||||
|
return sessionManager.getObjSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
Session getOpSession() throws PKCS11Exception {
|
||||||
|
return sessionManager.getOpSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
Session releaseSession(Session session) {
|
||||||
|
return sessionManager.releaseSession(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session killSession(Session session) {
|
||||||
|
return sessionManager.killSession(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_ATTRIBUTE[] getAttributes(String op, long type, long alg,
|
||||||
|
CK_ATTRIBUTE[] attrs) throws PKCS11Exception {
|
||||||
|
CK_ATTRIBUTE[] newAttrs =
|
||||||
|
templateManager.getAttributes(op, type, alg, attrs);
|
||||||
|
for (CK_ATTRIBUTE attr : newAttrs) {
|
||||||
|
if (attr.type == CKA_TOKEN) {
|
||||||
|
if (attr.getBoolean()) {
|
||||||
|
try {
|
||||||
|
ensureLoggedIn(null);
|
||||||
|
} catch (LoginException e) {
|
||||||
|
throw new ProviderException("Login failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// break once we have found a CKA_TOKEN attribute
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newAttrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
P11KeyFactory getKeyFactory(String algorithm) {
|
||||||
|
P11KeyFactory f;
|
||||||
|
if (algorithm.equals("RSA")) {
|
||||||
|
f = rsaFactory;
|
||||||
|
if (f == null) {
|
||||||
|
f = new P11RSAKeyFactory(this, algorithm);
|
||||||
|
rsaFactory = f;
|
||||||
|
}
|
||||||
|
} else if (algorithm.equals("DSA")) {
|
||||||
|
f = dsaFactory;
|
||||||
|
if (f == null) {
|
||||||
|
f = new P11DSAKeyFactory(this, algorithm);
|
||||||
|
dsaFactory = f;
|
||||||
|
}
|
||||||
|
} else if (algorithm.equals("DH")) {
|
||||||
|
f = dhFactory;
|
||||||
|
if (f == null) {
|
||||||
|
f = new P11DHKeyFactory(this, algorithm);
|
||||||
|
dhFactory = f;
|
||||||
|
}
|
||||||
|
} else if (algorithm.equals("EC")) {
|
||||||
|
f = ecFactory;
|
||||||
|
if (f == null) {
|
||||||
|
f = new P11ECKeyFactory(this, algorithm);
|
||||||
|
ecFactory = f;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ProviderException("Unknown algorithm " + algorithm);
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
P11SecureRandom getRandom() {
|
||||||
|
if (secureRandom == null) {
|
||||||
|
secureRandom = new P11SecureRandom(this);
|
||||||
|
}
|
||||||
|
return secureRandom;
|
||||||
|
}
|
||||||
|
|
||||||
|
P11KeyStore getKeyStore() {
|
||||||
|
if (keyStore == null) {
|
||||||
|
keyStore = new P11KeyStore(this);
|
||||||
|
}
|
||||||
|
return keyStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_MECHANISM_INFO getMechanismInfo(long mechanism) throws PKCS11Exception {
|
||||||
|
CK_MECHANISM_INFO result = mechInfoMap.get(mechanism);
|
||||||
|
if (result == null) {
|
||||||
|
try {
|
||||||
|
result = p11.C_GetMechanismInfo(provider.slotID,
|
||||||
|
mechanism);
|
||||||
|
mechInfoMap.put(mechanism, result);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
if (e.getErrorCode() != PKCS11Constants.CKR_MECHANISM_INVALID) {
|
||||||
|
throw e;
|
||||||
|
} else {
|
||||||
|
mechInfoMap.put(mechanism, INVALID_MECH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (result == INVALID_MECH) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized byte[] getTokenId() {
|
||||||
|
if (tokenId == null) {
|
||||||
|
SecureRandom random = JCAUtil.getSecureRandom();
|
||||||
|
tokenId = new byte[20];
|
||||||
|
random.nextBytes(tokenId);
|
||||||
|
serializedTokens.add(new WeakReference<Token>(this));
|
||||||
|
}
|
||||||
|
return tokenId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// list of all tokens that have been serialized within this VM
|
||||||
|
// NOTE that elements are never removed from this list
|
||||||
|
// the assumption is that the number of tokens that are serialized
|
||||||
|
// is relatively small
|
||||||
|
private static final List<Reference<Token>> serializedTokens =
|
||||||
|
new ArrayList<Reference<Token>>();
|
||||||
|
|
||||||
|
private Object writeReplace() throws ObjectStreamException {
|
||||||
|
if (isValid() == false) {
|
||||||
|
throw new InvalidObjectException("Token has been removed");
|
||||||
|
}
|
||||||
|
return new TokenRep(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the state of this object from the stream.
|
||||||
|
* <p>
|
||||||
|
* Deserialization of this object is not supported.
|
||||||
|
*
|
||||||
|
* @param stream the {@code ObjectInputStream} from which data is read
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
* @throws ClassNotFoundException if a serialized class cannot be loaded
|
||||||
|
*/
|
||||||
|
private void readObject(ObjectInputStream stream)
|
||||||
|
throws IOException, ClassNotFoundException {
|
||||||
|
throw new InvalidObjectException(
|
||||||
|
"Tokens are not directly deserializable");
|
||||||
|
}
|
||||||
|
|
||||||
|
// serialized representation of a token
|
||||||
|
// tokens can only be de-serialized within the same VM invocation
|
||||||
|
// and if the token has not been removed in the meantime
|
||||||
|
private static class TokenRep implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 3503721168218219807L;
|
||||||
|
|
||||||
|
private final byte[] tokenId;
|
||||||
|
|
||||||
|
TokenRep(Token token) {
|
||||||
|
tokenId = token.getTokenId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object readResolve() throws ObjectStreamException {
|
||||||
|
for (Reference<Token> tokenRef : serializedTokens) {
|
||||||
|
Token token = tokenRef.get();
|
||||||
|
if ((token != null) && token.isValid()) {
|
||||||
|
if (Arrays.equals(token.getTokenId(), tokenId)) {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new InvalidObjectException("Could not find token");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the necessary parameters required by
|
||||||
|
* the CKM_AES_CTR mechanism as defined in CK_AES_CTR_PARAMS structure.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_AES_CTR_PARAMS {
|
||||||
|
* CK_ULONG ulCounterBits;
|
||||||
|
* CK_BYTE cb[16];
|
||||||
|
* } CK_AES_CTR_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Yu-Ching Valerie Peng
|
||||||
|
* @since 1.7
|
||||||
|
*/
|
||||||
|
public class CK_AES_CTR_PARAMS {
|
||||||
|
|
||||||
|
private final long ulCounterBits;
|
||||||
|
private final byte cb[];
|
||||||
|
|
||||||
|
public CK_AES_CTR_PARAMS(byte[] cb) {
|
||||||
|
ulCounterBits = 128;
|
||||||
|
this.cb = cb.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulCounterBits: ");
|
||||||
|
buffer.append(ulCounterBits);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("cb: ");
|
||||||
|
buffer.append(Functions.toHexString(cb));
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_ATTRIBUTE includes the type, value and length of an attribute.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_ATTRIBUTE {
|
||||||
|
* CK_ATTRIBUTE_TYPE type;
|
||||||
|
* CK_VOID_PTR pValue;
|
||||||
|
* CK_ULONG ulValueLen;
|
||||||
|
* } CK_ATTRIBUTE;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_ATTRIBUTE {
|
||||||
|
|
||||||
|
// common attributes
|
||||||
|
// NOTE that CK_ATTRIBUTE is a mutable classes but these attributes
|
||||||
|
// *MUST NEVER* be modified, e.g. by using them in a
|
||||||
|
// C_GetAttributeValue() call!
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE TOKEN_FALSE =
|
||||||
|
new CK_ATTRIBUTE(CKA_TOKEN, false);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE SENSITIVE_FALSE =
|
||||||
|
new CK_ATTRIBUTE(CKA_SENSITIVE, false);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE EXTRACTABLE_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_EXTRACTABLE, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE ENCRYPT_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_ENCRYPT, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE DECRYPT_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_DECRYPT, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE WRAP_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_WRAP, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE UNWRAP_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_UNWRAP, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE SIGN_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_SIGN, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE VERIFY_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_VERIFY, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE SIGN_RECOVER_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_SIGN_RECOVER, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE VERIFY_RECOVER_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_VERIFY_RECOVER, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE DERIVE_TRUE =
|
||||||
|
new CK_ATTRIBUTE(CKA_DERIVE, true);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE ENCRYPT_NULL =
|
||||||
|
new CK_ATTRIBUTE(CKA_ENCRYPT);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE DECRYPT_NULL =
|
||||||
|
new CK_ATTRIBUTE(CKA_DECRYPT);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE WRAP_NULL =
|
||||||
|
new CK_ATTRIBUTE(CKA_WRAP);
|
||||||
|
|
||||||
|
public final static CK_ATTRIBUTE UNWRAP_NULL =
|
||||||
|
new CK_ATTRIBUTE(CKA_UNWRAP);
|
||||||
|
|
||||||
|
public CK_ATTRIBUTE() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_ATTRIBUTE(long type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_ATTRIBUTE(long type, Object pValue) {
|
||||||
|
this.type = type;
|
||||||
|
this.pValue = pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_ATTRIBUTE(long type, boolean value) {
|
||||||
|
this.type = type;
|
||||||
|
this.pValue = Boolean.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_ATTRIBUTE(long type, long value) {
|
||||||
|
this.type = type;
|
||||||
|
this.pValue = Long.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_ATTRIBUTE(long type, BigInteger value) {
|
||||||
|
this.type = type;
|
||||||
|
this.pValue = sun.security.pkcs11.P11Util.getMagnitude(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getBigInteger() {
|
||||||
|
if (pValue instanceof byte[] == false) {
|
||||||
|
throw new RuntimeException("Not a byte[]");
|
||||||
|
}
|
||||||
|
return new BigInteger(1, (byte[])pValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean() {
|
||||||
|
if (pValue instanceof Boolean == false) {
|
||||||
|
throw new RuntimeException
|
||||||
|
("Not a Boolean: " + pValue.getClass().getName());
|
||||||
|
}
|
||||||
|
return ((Boolean)pValue).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] getCharArray() {
|
||||||
|
if (pValue instanceof char[] == false) {
|
||||||
|
throw new RuntimeException("Not a char[]");
|
||||||
|
}
|
||||||
|
return (char[])pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getByteArray() {
|
||||||
|
if (pValue instanceof byte[] == false) {
|
||||||
|
throw new RuntimeException("Not a byte[]");
|
||||||
|
}
|
||||||
|
return (byte[])pValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLong() {
|
||||||
|
if (pValue instanceof Long == false) {
|
||||||
|
throw new RuntimeException
|
||||||
|
("Not a Long: " + pValue.getClass().getName());
|
||||||
|
}
|
||||||
|
return ((Long)pValue).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ATTRIBUTE_TYPE type;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VOID_PTR pValue;
|
||||||
|
* CK_ULONG ulValueLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public Object pValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_ATTRIBUTE.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_ATTRIBUTE
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
String prefix = Functions.getAttributeName(type) + " = ";
|
||||||
|
if (type == CKA_CLASS) {
|
||||||
|
return prefix + Functions.getObjectClassName(getLong());
|
||||||
|
} else if (type == CKA_KEY_TYPE) {
|
||||||
|
return prefix + Functions.getKeyName(getLong());
|
||||||
|
} else {
|
||||||
|
String s;
|
||||||
|
if (pValue instanceof char[]) {
|
||||||
|
s = new String((char[])pValue);
|
||||||
|
} else if (pValue instanceof byte[]) {
|
||||||
|
s = Functions.toHexString((byte[])pValue);
|
||||||
|
} else {
|
||||||
|
s = String.valueOf(pValue);
|
||||||
|
}
|
||||||
|
return prefix + s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the necessary parameters required by
|
||||||
|
* the CKM_AES_CCM mechanism as defined in CK_CCM_PARAMS structure.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_CCM_PARAMS {
|
||||||
|
* CK_ULONG ulDataLen;
|
||||||
|
* CK_BYTE_PTR pNonce;
|
||||||
|
* CK_ULONG ulNonceLen;
|
||||||
|
* CK_BYTE_PTR pAAD;
|
||||||
|
* CK_ULONG ulAADLen;
|
||||||
|
* CK_ULONG ulMACLen;
|
||||||
|
* } CK_CCM_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @since 13
|
||||||
|
*/
|
||||||
|
public class CK_CCM_PARAMS {
|
||||||
|
|
||||||
|
private final long dataLen;
|
||||||
|
private final byte[] nonce;
|
||||||
|
private final byte[] aad;
|
||||||
|
private final long macLen;
|
||||||
|
|
||||||
|
public CK_CCM_PARAMS(int tagLen, byte[] iv, byte[] aad, int dataLen) {
|
||||||
|
this.dataLen = dataLen;
|
||||||
|
this.nonce = iv;
|
||||||
|
this.aad = aad;
|
||||||
|
this.macLen = tagLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.append(Constants.INDENT);
|
||||||
|
sb.append("ulDataLen: ");
|
||||||
|
sb.append(dataLen);
|
||||||
|
sb.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
sb.append(Constants.INDENT);
|
||||||
|
sb.append("iv: ");
|
||||||
|
sb.append(Functions.toHexString(nonce));
|
||||||
|
sb.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
sb.append(Constants.INDENT);
|
||||||
|
sb.append("aad: ");
|
||||||
|
sb.append(Functions.toHexString(aad));
|
||||||
|
sb.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
sb.append(Constants.INDENT);
|
||||||
|
sb.append("tagLen: ");
|
||||||
|
sb.append(macLen);
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interface CK_CREATEMUTEX.
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public interface CK_CREATEMUTEX {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method CK_CREATEMUTEX
|
||||||
|
*
|
||||||
|
* @return The mutex (lock) object.
|
||||||
|
* @exception PKCS11Exception
|
||||||
|
*/
|
||||||
|
public Object CK_CREATEMUTEX() throws PKCS11Exception;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_C_INITIALIZE_ARGS contains the optional arguments for the
|
||||||
|
* C_Initialize function.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_C_INITIALIZE_ARGS {
|
||||||
|
* CK_CREATEMUTEX CreateMutex;
|
||||||
|
* CK_DESTROYMUTEX DestroyMutex;
|
||||||
|
* CK_LOCKMUTEX LockMutex;
|
||||||
|
* CK_UNLOCKMUTEX UnlockMutex;
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* CK_VOID_PTR pReserved;
|
||||||
|
* } CK_C_INITIALIZE_ARGS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_C_INITIALIZE_ARGS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CREATEMUTEX CreateMutex;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_CREATEMUTEX CreateMutex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_DESTROYMUTEX DestroyMutex;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_DESTROYMUTEX DestroyMutex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_LOCKMUTEX LockMutex;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_LOCKMUTEX LockMutex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_UNLOCKMUTEX UnlockMutex;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_UNLOCKMUTEX UnlockMutex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VOID_PTR pReserved;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public Object pReserved;
|
||||||
|
|
||||||
|
}
|
137
src/main/java/com/sunyard/security/pkcs11/wrapper/CK_DATE.java
Normal file
137
src/main/java/com/sunyard/security/pkcs11/wrapper/CK_DATE.java
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class .<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_DATE {
|
||||||
|
* CK_CHAR year[4];
|
||||||
|
* CK_CHAR month[2];
|
||||||
|
* CK_CHAR day[2];
|
||||||
|
* } CK_DATE;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_DATE implements Cloneable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CHAR year[4]; - the year ("1900" - "9999")
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] year; /* the year ("1900" - "9999") */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CHAR month[2]; - the month ("01" - "12")
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] month; /* the month ("01" - "12") */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CHAR day[2]; - the day ("01" - "31")
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] day; /* the day ("01" - "31") */
|
||||||
|
|
||||||
|
public CK_DATE(char[] year, char[] month, char[] day) {
|
||||||
|
this.year = year;
|
||||||
|
this.month = month;
|
||||||
|
this.day = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a (deep) clone of this object.
|
||||||
|
*
|
||||||
|
* @return A clone of this object.
|
||||||
|
*/
|
||||||
|
public Object clone() {
|
||||||
|
CK_DATE copy = null;
|
||||||
|
try {
|
||||||
|
copy = (CK_DATE) super.clone();
|
||||||
|
} catch (CloneNotSupportedException cnse) {
|
||||||
|
// re-throw as RuntimeException
|
||||||
|
throw (RuntimeException)
|
||||||
|
(new RuntimeException("Clone error").initCause(cnse));
|
||||||
|
}
|
||||||
|
copy.year = this.year.clone();
|
||||||
|
copy.month = this.month.clone();
|
||||||
|
copy.day = this.day.clone();
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_DATE.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_DATE
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(new String(day));
|
||||||
|
buffer.append('.');
|
||||||
|
buffer.append(new String(month));
|
||||||
|
buffer.append('.');
|
||||||
|
buffer.append(new String(year));
|
||||||
|
buffer.append(" (DD.MM.YYYY)");
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interface CK_DESTROYMUTEX.<p>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public interface CK_DESTROYMUTEX {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method CK_DESTROYMUTEX
|
||||||
|
*
|
||||||
|
* @param pMutex The mutex (lock) object.
|
||||||
|
* @exception PKCS11Exception
|
||||||
|
*/
|
||||||
|
public void CK_DESTROYMUTEX(Object pMutex) throws PKCS11Exception;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_ECDH1_DERIVE_PARAMS provides the parameters to the
|
||||||
|
* CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_ECDH1_DERIVE_PARAMS {
|
||||||
|
* CK_EC_KDF_TYPE kdf;
|
||||||
|
* CK_ULONG ulSharedDataLen;
|
||||||
|
* CK_BYTE_PTR pSharedData;
|
||||||
|
* CK_ULONG ulPublicDataLen;
|
||||||
|
* CK_BYTE_PTR pPublicData;
|
||||||
|
* } CK_ECDH1_DERIVE_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
*/
|
||||||
|
public class CK_ECDH1_DERIVE_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_EC_KDF_TYPE kdf;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long kdf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulSharedDataLen;
|
||||||
|
* CK_BYTE_PTR pSharedData;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pSharedData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulPublicDataLen;
|
||||||
|
* CK_BYTE_PTR pPublicData;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pPublicData;
|
||||||
|
|
||||||
|
public CK_ECDH1_DERIVE_PARAMS(long kdf, byte[] pSharedData, byte[] pPublicData) {
|
||||||
|
this.kdf = kdf;
|
||||||
|
this.pSharedData = pSharedData;
|
||||||
|
this.pPublicData = pPublicData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_PKCS5_PBKD2_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("kdf: 0x");
|
||||||
|
buffer.append(Functions.toFullHexString(kdf));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pSharedDataLen: ");
|
||||||
|
buffer.append(pSharedData.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pSharedData: ");
|
||||||
|
buffer.append(Functions.toHexString(pSharedData));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicDataLen: ");
|
||||||
|
buffer.append(pPublicData.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicData: ");
|
||||||
|
buffer.append(Functions.toHexString(pPublicData));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_ECDH2_DERIVE_PARAMS provides the parameters to the
|
||||||
|
* CKM_ECMQV_DERIVE mechanism.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_ECDH2_DERIVE_PARAMS {
|
||||||
|
* CK_EC_KDF_TYPE kdf;
|
||||||
|
* CK_ULONG ulSharedDataLen;
|
||||||
|
* CK_BYTE_PTR pSharedData;
|
||||||
|
* CK_ULONG ulPublicDataLen;
|
||||||
|
* CK_BYTE_PTR pPublicData;
|
||||||
|
* CK_ULONG ulPrivateDataLen;
|
||||||
|
* CK_OBJECT_HANDLE hPrivateData;
|
||||||
|
* CK_ULONG ulPublicDataLen2;
|
||||||
|
* CK_BYTE_PTR pPublicData2;
|
||||||
|
* } CK_ECDH2_DERIVE_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
*/
|
||||||
|
public class CK_ECDH2_DERIVE_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_EC_KDF_TYPE kdf;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long kdf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulSharedDataLen;
|
||||||
|
* CK_BYTE_PTR pSharedData;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pSharedData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulPublicDataLen;
|
||||||
|
* CK_BYTE_PTR pPublicData;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pPublicData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulPrivateDataLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulPrivateDataLen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_OBJECT_HANDLE hPrivateData;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long hPrivateData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulPublicDataLen2;
|
||||||
|
* CK_BYTE_PTR pPublicData2;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pPublicData2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_PKCS5_PBKD2_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("kdf: 0x");
|
||||||
|
buffer.append(Functions.toFullHexString(kdf));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pSharedDataLen: ");
|
||||||
|
buffer.append(pSharedData.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pSharedData: ");
|
||||||
|
buffer.append(Functions.toHexString(pSharedData));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicDataLen: ");
|
||||||
|
buffer.append(pPublicData.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicData: ");
|
||||||
|
buffer.append(Functions.toHexString(pPublicData));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulPrivateDataLen: ");
|
||||||
|
buffer.append(ulPrivateDataLen);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hPrivateData: ");
|
||||||
|
buffer.append(hPrivateData);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicDataLen2: ");
|
||||||
|
buffer.append(pPublicData2.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicData2: ");
|
||||||
|
buffer.append(Functions.toHexString(pPublicData2));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the necessary parameters required by
|
||||||
|
* the CKM_AES_GCM mechanism as defined in CK_GCM_PARAMS structure.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_GCM_PARAMS {
|
||||||
|
* CK_BYTE_PTR pIv;
|
||||||
|
* CK_ULONG ulIvLen;
|
||||||
|
* CK_BYTE_PTR pAAD;
|
||||||
|
* CK_ULONG ulAADLen;
|
||||||
|
* CK_ULONG ulTagBits;
|
||||||
|
* } CK_GCM_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @since 10
|
||||||
|
*/
|
||||||
|
public class CK_GCM_PARAMS {
|
||||||
|
|
||||||
|
private final byte[] iv;
|
||||||
|
private final byte[] aad;
|
||||||
|
private final long tagBits;
|
||||||
|
|
||||||
|
public CK_GCM_PARAMS(int tagLenInBits, byte[] iv, byte[] aad) {
|
||||||
|
this.iv = iv;
|
||||||
|
this.aad = aad;
|
||||||
|
this.tagBits = tagLenInBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.append(Constants.INDENT);
|
||||||
|
sb.append("iv: ");
|
||||||
|
sb.append(Functions.toHexString(iv));
|
||||||
|
sb.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
sb.append(Constants.INDENT);
|
||||||
|
sb.append("aad: ");
|
||||||
|
sb.append(Functions.toHexString(aad));
|
||||||
|
sb.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
sb.append(Constants.INDENT);
|
||||||
|
sb.append("tagLen(in bits): ");
|
||||||
|
sb.append(tagBits);
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
164
src/main/java/com/sunyard/security/pkcs11/wrapper/CK_INFO.java
Normal file
164
src/main/java/com/sunyard/security/pkcs11/wrapper/CK_INFO.java
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_INFO provides general information about Cryptoki.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_INFO {
|
||||||
|
* CK_VERSION cryptokiVersion;
|
||||||
|
* CK_UTF8CHAR manufacturerID[32];
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* CK_UTF8CHAR libraryDescription[32];
|
||||||
|
* CK_VERSION libraryVersion;
|
||||||
|
* } CK_INFO;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_INFO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cryptoki interface version number<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VERSION cryptokiVersion;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_VERSION cryptokiVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID of the Cryptoki library manufacturer. must be blank
|
||||||
|
* padded - only the first 32 chars will be used<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_UTF8CHAR manufacturerID[32];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] manufacturerID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bit flags reserved for future versions. must be zero<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long flags;
|
||||||
|
|
||||||
|
|
||||||
|
/* libraryDescription and libraryVersion are new for v2.0 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* must be blank padded - only the first 32 chars will be used<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_UTF8CHAR libraryDescription[32];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] libraryDescription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cryptoki library version number<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VERSION libraryVersion;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_VERSION libraryVersion;
|
||||||
|
|
||||||
|
public CK_INFO(CK_VERSION cryptoVer, char[] vendor, long flags,
|
||||||
|
char[] libDesc, CK_VERSION libVer) {
|
||||||
|
this.cryptokiVersion = cryptoVer;
|
||||||
|
this.manufacturerID = vendor;
|
||||||
|
this.flags = flags;
|
||||||
|
this.libraryDescription = libDesc;
|
||||||
|
this.libraryVersion = libVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_INFO.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_INFO
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("cryptokiVersion: ");
|
||||||
|
buffer.append(cryptokiVersion.toString());
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("manufacturerID: ");
|
||||||
|
buffer.append(new String(manufacturerID));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("flags: ");
|
||||||
|
buffer.append(Functions.toBinaryString(flags));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("libraryDescription: ");
|
||||||
|
buffer.append(new String(libraryDescription));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("libraryVersion: ");
|
||||||
|
buffer.append(libraryVersion.toString());
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interface CK_LOCKMUTEX<p>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public interface CK_LOCKMUTEX {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method CK_LOCKMUTEX
|
||||||
|
*
|
||||||
|
* @param pMutex The mutex (lock) object to lock.
|
||||||
|
* @exception PKCS11Exception
|
||||||
|
*/
|
||||||
|
public void CK_LOCKMUTEX(Object pMutex) throws PKCS11Exception;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_MECHANISM specifies a particular mechanism and any parameters it
|
||||||
|
* requires.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_MECHANISM {
|
||||||
|
* CK_MECHANISM_TYPE mechanism;
|
||||||
|
* CK_VOID_PTR pParameter;
|
||||||
|
* CK_ULONG ulParameterLen;
|
||||||
|
* } CK_MECHANISM;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_MECHANISM {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_MECHANISM_TYPE mechanism;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long mechanism;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VOID_PTR pParameter;
|
||||||
|
* CK_ULONG ulParameterLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public Object pParameter = null;
|
||||||
|
|
||||||
|
// pointer to native CK_MECHANISM structure
|
||||||
|
// For mechanisms which have only mechanism id, the native structure
|
||||||
|
// can be freed right after init and this field will not be used. However,
|
||||||
|
// for mechanisms which have both mechanism id and parameters, it can
|
||||||
|
// only be freed after operation is finished. Thus, the native pointer
|
||||||
|
// will be stored here and then be explicitly freed by caller.
|
||||||
|
private long pHandle = 0L;
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism) {
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't have a (long,Object) constructor to force type checking.
|
||||||
|
// This makes sure we don't accidentally pass a class that the native
|
||||||
|
// code cannot handle.
|
||||||
|
public CK_MECHANISM(long mechanism, byte[] pParameter) {
|
||||||
|
init(mechanism, pParameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, BigInteger b) {
|
||||||
|
init(mechanism, sun.security.pkcs11.P11Util.getMagnitude(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_VERSION version) {
|
||||||
|
init(mechanism, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_SSL3_MASTER_KEY_DERIVE_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_TLS12_MASTER_KEY_DERIVE_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_SSL3_KEY_MAT_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_TLS12_KEY_MAT_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_TLS_PRF_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_TLS_MAC_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_ECDH1_DERIVE_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, Long params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_AES_CTR_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_GCM_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CK_MECHANISM(long mechanism, CK_CCM_PARAMS params) {
|
||||||
|
init(mechanism, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For PSS. the parameter may be set multiple times, use the
|
||||||
|
// CK_MECHANISM(long) constructor and setParameter(CK_RSA_PKCS_PSS_PARAMS)
|
||||||
|
// methods instead of creating yet another constructor
|
||||||
|
public void setParameter(CK_RSA_PKCS_PSS_PARAMS params) {
|
||||||
|
assert(this.mechanism == CKM_RSA_PKCS_PSS);
|
||||||
|
assert(params != null);
|
||||||
|
if (this.pParameter != null && this.pParameter.equals(params)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
freeHandle();
|
||||||
|
this.pParameter = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void freeHandle() {
|
||||||
|
if (this.pHandle != 0L) {
|
||||||
|
this.pHandle = PKCS11.freeMechanism(pHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(long mechanism, Object pParameter) {
|
||||||
|
this.mechanism = mechanism;
|
||||||
|
this.pParameter = pParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_MECHANISM.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_MECHANISM
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("mechanism: ");
|
||||||
|
buffer.append(mechanism);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pParameter: ");
|
||||||
|
buffer.append(pParameter.toString());
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulParameterLen: ??");
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
*/
|
||||||
|
if (pHandle != 0L) {
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pHandle: ");
|
||||||
|
buffer.append(pHandle);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
}
|
||||||
|
return buffer.toString() ;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
import java.security.ProviderException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_MECHANISM_INFO provides information about a particular mechanism.
|
||||||
|
* <p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_MECHANISM_INFO {
|
||||||
|
* CK_ULONG ulMinKeySize;
|
||||||
|
* CK_ULONG ulMaxKeySize;
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* } CK_MECHANISM_INFO;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_MECHANISM_INFO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMinKeySize;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMinKeySize;
|
||||||
|
|
||||||
|
// the integer version of ulMinKeySize for doing the actual range
|
||||||
|
// check in SunPKCS11 provider, defaults to 0
|
||||||
|
public final int iMinKeySize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMaxKeySize;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMaxKeySize;
|
||||||
|
|
||||||
|
// the integer version of ulMaxKeySize for doing the actual range
|
||||||
|
// check in SunPKCS11 provider, defaults to Integer.MAX_VALUE
|
||||||
|
public final int iMaxKeySize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long flags;
|
||||||
|
|
||||||
|
public CK_MECHANISM_INFO(long minKeySize, long maxKeySize,
|
||||||
|
long flags) {
|
||||||
|
this.ulMinKeySize = minKeySize;
|
||||||
|
this.ulMaxKeySize = maxKeySize;
|
||||||
|
this.iMinKeySize = ((minKeySize < Integer.MAX_VALUE && minKeySize > 0)?
|
||||||
|
(int)minKeySize : 0);
|
||||||
|
this.iMaxKeySize = ((maxKeySize < Integer.MAX_VALUE && maxKeySize > 0)?
|
||||||
|
(int)maxKeySize : Integer.MAX_VALUE);
|
||||||
|
this.flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_MECHANISM_INFO.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_MECHANISM_INFO
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulMinKeySize: ");
|
||||||
|
buffer.append(String.valueOf(ulMinKeySize));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulMaxKeySize: ");
|
||||||
|
buffer.append(String.valueOf(ulMaxKeySize));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("flags: ");
|
||||||
|
buffer.append(String.valueOf(flags));
|
||||||
|
buffer.append(" = ");
|
||||||
|
buffer.append(Functions.mechanismInfoFlagsToString(flags));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString() ;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interface CK_NOTIFY.<p>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public interface CK_NOTIFY {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method CK_NOTIFY
|
||||||
|
*
|
||||||
|
* @param hSession
|
||||||
|
* @param event
|
||||||
|
* @param pApplication
|
||||||
|
* @exception PKCS11Exception
|
||||||
|
*/
|
||||||
|
public void CK_NOTIFY(long hSession, long event, Object pApplication) throws PKCS11Exception;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_PBE_PARAMS provides all of the necessary information required byte
|
||||||
|
* the CKM_PBE mechanisms and the CKM_PBA_SHA1_WITH_SHA1_HMAC mechanism.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_PBE_PARAMS {
|
||||||
|
* CK_CHAR_PTR pInitVector;
|
||||||
|
* CK_CHAR_PTR pPassword;
|
||||||
|
* CK_ULONG ulPasswordLen;
|
||||||
|
* CK_CHAR_PTR pSalt;
|
||||||
|
* CK_ULONG ulSaltLen;
|
||||||
|
* CK_ULONG ulIteration;
|
||||||
|
* } CK_PBE_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_PBE_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CHAR_PTR pInitVector;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] pInitVector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CHAR_PTR pPassword;
|
||||||
|
* CK_ULONG ulPasswordLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] pPassword;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CHAR_PTR pSalt
|
||||||
|
* CK_ULONG ulSaltLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] pSalt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulIteration;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulIteration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_PBE_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_PBE_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pInitVector: ");
|
||||||
|
buffer.append(pInitVector);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulPasswordLen: ");
|
||||||
|
buffer.append(pPassword.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulSaltLen: ");
|
||||||
|
buffer.append(pSalt.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pSalt: ");
|
||||||
|
buffer.append(pSalt);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulIteration: ");
|
||||||
|
buffer.append(ulIteration);
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_PKCS5_PBKD2_PARAMS provides the parameters to the CKM_PKCS5_PBKD2
|
||||||
|
* mechanism.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_PKCS5_PBKD2_PARAMS {
|
||||||
|
* CK_PKCS5_PBKD2_SALT_SOURCE_TYPE saltSource;
|
||||||
|
* CK_VOID_PTR pSaltSourceData;
|
||||||
|
* CK_ULONG ulSaltSourceDataLen;
|
||||||
|
* CK_ULONG iterations;
|
||||||
|
* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
|
||||||
|
* CK_VOID_PTR pPrfData;
|
||||||
|
* CK_ULONG ulPrfDataLen;
|
||||||
|
* } CK_PKCS5_PBKD2_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_PKCS5_PBKD2_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long saltSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VOID_PTR pSaltSourceData;
|
||||||
|
* CK_ULONG ulSaltSourceDataLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pSaltSourceData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG iterations;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long iterations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long prf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VOID_PTR pPrfData;
|
||||||
|
* CK_ULONG ulPrfDataLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pPrfData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_PKCS5_PBKD2_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("saltSource: ");
|
||||||
|
buffer.append(saltSource);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pSaltSourceData: ");
|
||||||
|
buffer.append(Functions.toHexString(pSaltSourceData));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulSaltSourceDataLen: ");
|
||||||
|
buffer.append(pSaltSourceData.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("iterations: ");
|
||||||
|
buffer.append(iterations);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("prf: ");
|
||||||
|
buffer.append(prf);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPrfData: ");
|
||||||
|
buffer.append(Functions.toHexString(pPrfData));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulPrfDataLen: ");
|
||||||
|
buffer.append(pPrfData.length);
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
|
||||||
|
* CKM_RSA_PKCS_OAEP mechanism.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_RSA_PKCS_OAEP_PARAMS {
|
||||||
|
* CK_MECHANISM_TYPE hashAlg;
|
||||||
|
* CK_RSA_PKCS_OAEP_MGF_TYPE mgf;
|
||||||
|
* CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
|
||||||
|
* CK_VOID_PTR pSourceData;
|
||||||
|
* CK_ULONG ulSourceDataLen;
|
||||||
|
* } CK_RSA_PKCS_OAEP_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_RSA_PKCS_OAEP_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_MECHANISM_TYPE hashAlg;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long hashAlg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_RSA_PKCS_OAEP_MGF_TYPE mgf;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long mgf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VOID_PTR pSourceData;
|
||||||
|
* CK_ULONG ulSourceDataLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pSourceData;
|
||||||
|
|
||||||
|
//CK_ULONG ulSourceDataLen;
|
||||||
|
// ulSourceDataLen == pSourceData.length
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_RSA_PKCS_OAEP_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_RSA_PKCS_OAEP_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hashAlg: ");
|
||||||
|
buffer.append(hashAlg);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("mgf: ");
|
||||||
|
buffer.append(mgf);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("source: ");
|
||||||
|
buffer.append(source);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pSourceData: ");
|
||||||
|
buffer.append(pSourceData.toString());
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pSourceDataLen: ");
|
||||||
|
buffer.append(Functions.toHexString(pSourceData));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
import java.security.ProviderException;
|
||||||
|
import java.security.spec.PSSParameterSpec;
|
||||||
|
import java.security.spec.MGF1ParameterSpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the necessary parameters required by the
|
||||||
|
* CKM_RSA_PKCS_PSS mechanism as defined in CK_RSA_PKCS_PSS_PARAMS structure.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_RSA_PKCS_PSS_PARAMS {
|
||||||
|
* CK_MECHANISM_TYPE hashAlg;
|
||||||
|
* CK_RSA_PKCS_MGF_TYPE mgf;
|
||||||
|
* CK_ULONG sLen;
|
||||||
|
* } CK_RSA_PKCS_PSS_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @since 13
|
||||||
|
*/
|
||||||
|
public class CK_RSA_PKCS_PSS_PARAMS {
|
||||||
|
|
||||||
|
private final long hashAlg;
|
||||||
|
private final long mgf;
|
||||||
|
private final long sLen;
|
||||||
|
|
||||||
|
public CK_RSA_PKCS_PSS_PARAMS(String hashAlg, String mgfAlg,
|
||||||
|
String mgfHash, int sLen) {
|
||||||
|
this.hashAlg = Functions.getHashMechId(hashAlg);
|
||||||
|
if (!mgfAlg.equals("MGF1")) {
|
||||||
|
throw new ProviderException("Only MGF1 is supported");
|
||||||
|
}
|
||||||
|
// no dash in PKCS#11 mechanism names
|
||||||
|
this.mgf = Functions.getMGFId("CKG_MGF1_" + hashAlg.replaceFirst("-", ""));
|
||||||
|
this.sLen = sLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(o instanceof CK_RSA_PKCS_PSS_PARAMS)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RSA_PKCS_PSS_PARAMS other = (CK_RSA_PKCS_PSS_PARAMS) o;
|
||||||
|
return ((other.hashAlg == hashAlg) &&
|
||||||
|
(other.mgf == mgf) &&
|
||||||
|
(other.sLen == sLen));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (int)(hashAlg << 2 + mgf << 1 + sLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hashAlg: ");
|
||||||
|
buffer.append(Functions.toFullHexString(hashAlg));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("mgf: ");
|
||||||
|
buffer.append(Functions.toFullHexString(mgf));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("sLen(in bytes): ");
|
||||||
|
buffer.append(sLen);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_SESSION_INFO provides information about a session.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_SESSION_INFO {
|
||||||
|
* CK_SLOT_ID slotID;
|
||||||
|
* CK_STATE state;
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* CK_ULONG ulDeviceError;
|
||||||
|
* } CK_SESSION_INFO;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_SESSION_INFO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_SLOT_ID slotID;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long slotID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_STATE state;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long flags; /* see below */
|
||||||
|
|
||||||
|
/* ulDeviceError was changed from CK_USHORT to CK_ULONG for
|
||||||
|
* v2.0 */
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulDeviceError;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulDeviceError; /* device-dependent error code */
|
||||||
|
|
||||||
|
public CK_SESSION_INFO(long slotID, long state,
|
||||||
|
long flags, long ulDeviceError) {
|
||||||
|
this.slotID = slotID;
|
||||||
|
this.state = state;
|
||||||
|
this.flags = flags;
|
||||||
|
this.ulDeviceError = ulDeviceError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_SESSION_INFO.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_SESSION_INFO
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("slotID: ");
|
||||||
|
buffer.append(String.valueOf(slotID));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("state: ");
|
||||||
|
buffer.append(Functions.sessionStateToString(state));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("flags: ");
|
||||||
|
buffer.append(Functions.sessionInfoFlagsToString(flags));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulDeviceError: ");
|
||||||
|
buffer.append(Functions.toHexString(ulDeviceError));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_SLOT_INFO provides information about a slot.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_SLOT_INFO {
|
||||||
|
* CK_UTF8CHAR slotDescription[64];
|
||||||
|
* CK_UTF8CHAR manufacturerID[32];
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* CK_VERSION hardwareVersion;
|
||||||
|
* CK_VERSION firmwareVersion;
|
||||||
|
* } CK_SLOT_INFO;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_SLOT_INFO {
|
||||||
|
|
||||||
|
/* slotDescription and manufacturerID have been changed from
|
||||||
|
* CK_CHAR to CK_UTF8CHAR for v2.11. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* must be blank padded and only the first 64 chars will be used<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_UTF8CHAR slotDescription[64];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] slotDescription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* must be blank padded and only the first 32 chars will be used<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_UTF8CHAR manufacturerID[32];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] manufacturerID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long flags;
|
||||||
|
|
||||||
|
/* hardwareVersion and firmwareVersion are new for v2.0 */
|
||||||
|
/**
|
||||||
|
* version of hardware<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VERSION hardwareVersion;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_VERSION hardwareVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* version of firmware<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VERSION firmwareVersion;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_VERSION firmwareVersion;
|
||||||
|
|
||||||
|
public CK_SLOT_INFO(char[] slotDesc, char[] vendor,
|
||||||
|
long flags, CK_VERSION hwVer, CK_VERSION fwVer) {
|
||||||
|
this.slotDescription = slotDesc;
|
||||||
|
this.manufacturerID = vendor;
|
||||||
|
this.flags = flags;
|
||||||
|
this.hardwareVersion = hwVer;
|
||||||
|
this.firmwareVersion = fwVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_SLOT_INFO.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_SLOT_INFO
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("slotDescription: ");
|
||||||
|
buffer.append(new String(slotDescription));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("manufacturerID: ");
|
||||||
|
buffer.append(new String(manufacturerID));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("flags: ");
|
||||||
|
buffer.append(Functions.slotInfoFlagsToString(flags));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hardwareVersion: ");
|
||||||
|
buffer.append(hardwareVersion.toString());
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("firmwareVersion: ");
|
||||||
|
buffer.append(firmwareVersion.toString());
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_SSL3_KEY_MAT_OUT contains the resulting key handles and
|
||||||
|
* initialization vectors after performing a C_DeriveKey function with the
|
||||||
|
* CKM_SSL3_KEY_AND_MAC_DERIVE mechanism.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_SSL3_KEY_MAT_OUT {
|
||||||
|
* CK_OBJECT_HANDLE hClientMacSecret;
|
||||||
|
* CK_OBJECT_HANDLE hServerMacSecret;
|
||||||
|
* CK_OBJECT_HANDLE hClientKey;
|
||||||
|
* CK_OBJECT_HANDLE hServerKey;
|
||||||
|
* CK_BYTE_PTR pIVClient;
|
||||||
|
* CK_BYTE_PTR pIVServer;
|
||||||
|
* } CK_SSL3_KEY_MAT_OUT;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_SSL3_KEY_MAT_OUT{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_OBJECT_HANDLE hClientMacSecret;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long hClientMacSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_OBJECT_HANDLE hServerMacSecret;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long hServerMacSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_OBJECT_HANDLE hClientKey;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long hClientKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_OBJECT_HANDLE hServerKey;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long hServerKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_BYTE_PTR pIVClient;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pIVClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_BYTE_PTR pIVServer;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pIVServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_SSL3_KEY_MAT_OUT.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_SSL3_KEY_MAT_OUT
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hClientMacSecret: ");
|
||||||
|
buffer.append(hClientMacSecret);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hServerMacSecret: ");
|
||||||
|
buffer.append(hServerMacSecret);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hClientKey: ");
|
||||||
|
buffer.append(hClientKey);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hServerKey: ");
|
||||||
|
buffer.append(hServerKey);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pIVClient: ");
|
||||||
|
buffer.append(Functions.toHexString(pIVClient));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pIVServer: ");
|
||||||
|
buffer.append(Functions.toHexString(pIVServer));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_SSL3_KEY_MAT_PARAMS provides the parameters to the
|
||||||
|
* CKM_SSL3_KEY_AND_MAC_DERIVE mechanism.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_SSL3_KEY_MAT_PARAMS {
|
||||||
|
* CK_ULONG ulMacSizeInBits;
|
||||||
|
* CK_ULONG ulKeySizeInBits;
|
||||||
|
* CK_ULONG ulIVSizeInBits;
|
||||||
|
* CK_BBOOL bIsExport;
|
||||||
|
* CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
* CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
|
||||||
|
* } CK_SSL3_KEY_MAT_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_SSL3_KEY_MAT_PARAMS{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMacSizeInBits;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMacSizeInBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulKeySizeInBits;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulKeySizeInBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulIVSizeInBits;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulIVSizeInBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_BBOOL bIsExport;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public boolean bIsExport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_SSL3_KEY_MAT_OUT pReturnedKeyMaterial;
|
||||||
|
|
||||||
|
public CK_SSL3_KEY_MAT_PARAMS(int macSize, int keySize, int ivSize, boolean export, CK_SSL3_RANDOM_DATA random) {
|
||||||
|
ulMacSizeInBits = macSize;
|
||||||
|
ulKeySizeInBits = keySize;
|
||||||
|
ulIVSizeInBits = ivSize;
|
||||||
|
bIsExport = export;
|
||||||
|
RandomInfo = random;
|
||||||
|
pReturnedKeyMaterial = new CK_SSL3_KEY_MAT_OUT();
|
||||||
|
if (ivSize != 0) {
|
||||||
|
int n = ivSize >> 3;
|
||||||
|
pReturnedKeyMaterial.pIVClient = new byte[n];
|
||||||
|
pReturnedKeyMaterial.pIVServer = new byte[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_SSL3_KEY_MAT_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_SSL3_KEY_MAT_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulMacSizeInBits: ");
|
||||||
|
buffer.append(ulMacSizeInBits);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulKeySizeInBits: ");
|
||||||
|
buffer.append(ulKeySizeInBits);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulIVSizeInBits: ");
|
||||||
|
buffer.append(ulIVSizeInBits);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("bIsExport: ");
|
||||||
|
buffer.append(bIsExport);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("RandomInfo: ");
|
||||||
|
buffer.append(RandomInfo);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pReturnedKeyMaterial: ");
|
||||||
|
buffer.append(pReturnedKeyMaterial);
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_SSL3_MASTER_KEY_DERIVE_PARAMS provides the parameters to the
|
||||||
|
* CKM_SSL3_MASTER_KEY_DERIVE mechanism.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
|
||||||
|
* CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
* CK_VERSION_PTR pVersion;
|
||||||
|
* } CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VERSION_PTR pVersion;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_VERSION pVersion;
|
||||||
|
|
||||||
|
public CK_SSL3_MASTER_KEY_DERIVE_PARAMS(CK_SSL3_RANDOM_DATA random, CK_VERSION version) {
|
||||||
|
RandomInfo = random;
|
||||||
|
pVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_SSL3_MASTER_KEY_DERIVE_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_SSL3_MASTER_KEY_DERIVE_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("RandomInfo: ");
|
||||||
|
buffer.append(RandomInfo);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pVersion: ");
|
||||||
|
buffer.append(pVersion);
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_SSL3_RANDOM_DATA provides information about the random data of a
|
||||||
|
* client and a server in an SSL context. This class is used by both the
|
||||||
|
* CKM_SSL3_MASTER_KEY_DERIVE and the CKM_SSL3_KEY_AND_MAC_DERIVE mechanisms.
|
||||||
|
* <p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_SSL3_RANDOM_DATA {
|
||||||
|
* CK_BYTE_PTR pClientRandom;
|
||||||
|
* CK_ULONG ulClientRandomLen;
|
||||||
|
* CK_BYTE_PTR pServerRandom;
|
||||||
|
* CK_ULONG ulServerRandomLen;
|
||||||
|
* } CK_SSL3_RANDOM_DATA;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_SSL3_RANDOM_DATA {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_BYTE_PTR pClientRandom;
|
||||||
|
* CK_ULONG ulClientRandomLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pClientRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_BYTE_PTR pServerRandom;
|
||||||
|
* CK_ULONG ulServerRandomLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pServerRandom;
|
||||||
|
|
||||||
|
public CK_SSL3_RANDOM_DATA(byte[] clientRandom, byte[] serverRandom) {
|
||||||
|
pClientRandom = clientRandom;
|
||||||
|
pServerRandom = serverRandom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_SSL3_RANDOM_DATA.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_SSL3_RANDOM_DATA
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pClientRandom: ");
|
||||||
|
buffer.append(Functions.toHexString(pClientRandom));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulClientRandomLen: ");
|
||||||
|
buffer.append(pClientRandom.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pServerRandom: ");
|
||||||
|
buffer.append(Functions.toHexString(pServerRandom));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulServerRandomLen: ");
|
||||||
|
buffer.append(pServerRandom.length);
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Red Hat, Inc. and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CK_TLS12_KEY_MAT_PARAMS from PKCS#11 v2.40.
|
||||||
|
*/
|
||||||
|
public class CK_TLS12_KEY_MAT_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMacSizeInBits;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMacSizeInBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulKeySizeInBits;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulKeySizeInBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulIVSizeInBits;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulIVSizeInBits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_BBOOL bIsExport;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public boolean bIsExport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_SSL3_KEY_MAT_OUT pReturnedKeyMaterial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_MECHANISM_TYPE prfHashMechanism;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long prfHashMechanism;
|
||||||
|
|
||||||
|
public CK_TLS12_KEY_MAT_PARAMS(
|
||||||
|
int macSize, int keySize, int ivSize, boolean export,
|
||||||
|
CK_SSL3_RANDOM_DATA random, long prfHashMechanism) {
|
||||||
|
ulMacSizeInBits = macSize;
|
||||||
|
ulKeySizeInBits = keySize;
|
||||||
|
ulIVSizeInBits = ivSize;
|
||||||
|
bIsExport = export;
|
||||||
|
RandomInfo = random;
|
||||||
|
pReturnedKeyMaterial = new CK_SSL3_KEY_MAT_OUT();
|
||||||
|
if (ivSize != 0) {
|
||||||
|
int n = ivSize >> 3;
|
||||||
|
pReturnedKeyMaterial.pIVClient = new byte[n];
|
||||||
|
pReturnedKeyMaterial.pIVServer = new byte[n];
|
||||||
|
}
|
||||||
|
this.prfHashMechanism = prfHashMechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_TLS12_KEY_MAT_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_TLS12_KEY_MAT_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulMacSizeInBits: ");
|
||||||
|
buffer.append(ulMacSizeInBits);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulKeySizeInBits: ");
|
||||||
|
buffer.append(ulKeySizeInBits);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulIVSizeInBits: ");
|
||||||
|
buffer.append(ulIVSizeInBits);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("bIsExport: ");
|
||||||
|
buffer.append(bIsExport);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("RandomInfo: ");
|
||||||
|
buffer.append(RandomInfo);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pReturnedKeyMaterial: ");
|
||||||
|
buffer.append(pReturnedKeyMaterial);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("prfHashMechanism: ");
|
||||||
|
buffer.append(prfHashMechanism);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Red Hat, Inc. and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CK_TLS12_MASTER_KEY_DERIVE_PARAMS from PKCS#11 v2.40.
|
||||||
|
*/
|
||||||
|
public class CK_TLS12_MASTER_KEY_DERIVE_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_SSL3_RANDOM_DATA RandomInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VERSION_PTR pVersion;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_VERSION pVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_MECHANISM_TYPE prfHashMechanism;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long prfHashMechanism;
|
||||||
|
|
||||||
|
public CK_TLS12_MASTER_KEY_DERIVE_PARAMS(
|
||||||
|
CK_SSL3_RANDOM_DATA random, CK_VERSION version,
|
||||||
|
long prfHashMechanism) {
|
||||||
|
RandomInfo = random;
|
||||||
|
pVersion = version;
|
||||||
|
this.prfHashMechanism = prfHashMechanism;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Red Hat, Inc. and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CK_TLS_MAC_PARAMS from PKCS#11 v2.40.
|
||||||
|
*/
|
||||||
|
public class CK_TLS_MAC_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_MECHANISM_TYPE prfMechanism;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long prfMechanism;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMacLength;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMacLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulServerOrClient;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulServerOrClient;
|
||||||
|
|
||||||
|
public CK_TLS_MAC_PARAMS(long prfMechanism,
|
||||||
|
long ulMacLength, long ulServerOrClient) {
|
||||||
|
this.prfMechanism = prfMechanism;
|
||||||
|
this.ulMacLength = ulMacLength;
|
||||||
|
this.ulServerOrClient = ulServerOrClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CK_TLS_PRF_PARAMS from PKCS#11 v2.20.
|
||||||
|
*
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
public class CK_TLS_PRF_PARAMS {
|
||||||
|
|
||||||
|
public byte[] pSeed;
|
||||||
|
public byte[] pLabel;
|
||||||
|
public byte[] pOutput;
|
||||||
|
|
||||||
|
public CK_TLS_PRF_PARAMS(byte[] pSeed, byte[] pLabel, byte[] pOutput) {
|
||||||
|
this.pSeed = pSeed;
|
||||||
|
this.pLabel = pLabel;
|
||||||
|
this.pOutput = pOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,389 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_TOKEN_INFO provides information about a token.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_TOKEN_INFO {
|
||||||
|
* CK_UTF8CHAR label[32];
|
||||||
|
* CK_UTF8CHAR manufacturerID[32];
|
||||||
|
* CK_UTF8CHAR model[16];
|
||||||
|
* CK_CHAR serialNumber[16];
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* CK_ULONG ulMaxSessionCount;
|
||||||
|
* CK_ULONG ulSessionCount;
|
||||||
|
* CK_ULONG ulMaxRwSessionCount;
|
||||||
|
* CK_ULONG ulRwSessionCount;
|
||||||
|
* CK_ULONG ulMaxPinLen;
|
||||||
|
* CK_ULONG ulMinPinLen;
|
||||||
|
* CK_ULONG ulTotalPublicMemory;
|
||||||
|
* CK_ULONG ulFreePublicMemory;
|
||||||
|
* CK_ULONG ulTotalPrivateMemory;
|
||||||
|
* CK_ULONG ulFreePrivateMemory;
|
||||||
|
* CK_VERSION hardwareVersion;
|
||||||
|
* CK_VERSION firmwareVersion;
|
||||||
|
* CK_CHAR utcTime[16];
|
||||||
|
* } CK_TOKEN_INFO;
|
||||||
|
*
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_TOKEN_INFO {
|
||||||
|
|
||||||
|
/* label, manufacturerID, and model have been changed from
|
||||||
|
* CK_CHAR to CK_UTF8CHAR for v2.11. */
|
||||||
|
/**
|
||||||
|
* must be blank padded and only the first 32 chars will be used<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_UTF8CHAR label[32];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] label; /* blank padded */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* must be blank padded and only the first 32 chars will be used<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_UTF8CHAR manufacturerID[32];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] manufacturerID; /* blank padded */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* must be blank padded and only the first 16 chars will be used<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_UTF8CHAR model[16];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] model; /* blank padded */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* must be blank padded and only the first 16 chars will be used<p>
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CHAR serialNumber[16];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] serialNumber; /* blank padded */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_FLAGS flags;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long flags; /* see below */
|
||||||
|
|
||||||
|
/* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
|
||||||
|
* ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
|
||||||
|
* changed from CK_USHORT to CK_ULONG for v2.0 */
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMaxSessionCount;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMaxSessionCount; /* max open sessions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulSessionCount;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulSessionCount; /* sess. now open */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMaxRwSessionCount;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMaxRwSessionCount; /* max R/W sessions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulRwSessionCount;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulRwSessionCount; /* R/W sess. now open */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMaxPinLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMaxPinLen; /* in bytes */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulMinPinLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulMinPinLen; /* in bytes */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulTotalPublicMemory;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulTotalPublicMemory; /* in bytes */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulFreePublicMemory;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulFreePublicMemory; /* in bytes */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulTotalPrivateMemory;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulTotalPrivateMemory; /* in bytes */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulFreePrivateMemory;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulFreePrivateMemory; /* in bytes */
|
||||||
|
|
||||||
|
/* hardwareVersion, firmwareVersion, and time are new for
|
||||||
|
* v2.0 */
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VERSION hardwareVersion;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_VERSION hardwareVersion; /* version of hardware */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_VERSION firmwareVersion;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public CK_VERSION firmwareVersion; /* version of firmware */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* only the first 16 chars will be used
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_CHAR utcTime[16];
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public char[] utcTime; /* time */
|
||||||
|
|
||||||
|
public CK_TOKEN_INFO(char[] label, char[] vendor, char[] model,
|
||||||
|
char[] serialNo, long flags,
|
||||||
|
long sessionMax, long session,
|
||||||
|
long rwSessionMax, long rwSession,
|
||||||
|
long pinLenMax, long pinLenMin,
|
||||||
|
long totalPubMem, long freePubMem,
|
||||||
|
long totalPrivMem, long freePrivMem,
|
||||||
|
CK_VERSION hwVer, CK_VERSION fwVer, char[] utcTime) {
|
||||||
|
this.label = label;
|
||||||
|
this.manufacturerID = vendor;
|
||||||
|
this.model = model;
|
||||||
|
this.serialNumber = serialNo;
|
||||||
|
this.flags = flags;
|
||||||
|
this.ulMaxSessionCount = sessionMax;
|
||||||
|
this.ulSessionCount = session;
|
||||||
|
this.ulMaxRwSessionCount = rwSessionMax;
|
||||||
|
this.ulRwSessionCount = rwSession;
|
||||||
|
this.ulMaxPinLen = pinLenMax;
|
||||||
|
this.ulMinPinLen = pinLenMin;
|
||||||
|
this.ulTotalPublicMemory = totalPubMem;
|
||||||
|
this.ulFreePublicMemory = freePubMem;
|
||||||
|
this.ulTotalPrivateMemory = totalPrivMem;
|
||||||
|
this.ulFreePrivateMemory = freePrivMem;
|
||||||
|
this.hardwareVersion = hwVer;
|
||||||
|
this.firmwareVersion = fwVer;
|
||||||
|
this.utcTime = utcTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_TOKEN_INFO.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_TOKEN_INFO
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("label: ");
|
||||||
|
buffer.append(new String(label));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("manufacturerID: ");
|
||||||
|
buffer.append(new String(manufacturerID));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("model: ");
|
||||||
|
buffer.append(new String(model));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("serialNumber: ");
|
||||||
|
buffer.append(new String(serialNumber));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("flags: ");
|
||||||
|
buffer.append(Functions.tokenInfoFlagsToString(flags));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulMaxSessionCount: ");
|
||||||
|
buffer.append((ulMaxSessionCount == PKCS11Constants.CK_EFFECTIVELY_INFINITE)
|
||||||
|
? "CK_EFFECTIVELY_INFINITE"
|
||||||
|
: (ulMaxSessionCount == PKCS11Constants.CK_UNAVAILABLE_INFORMATION)
|
||||||
|
? "CK_UNAVAILABLE_INFORMATION"
|
||||||
|
: String.valueOf(ulMaxSessionCount));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulSessionCount: ");
|
||||||
|
buffer.append((ulSessionCount == PKCS11Constants.CK_UNAVAILABLE_INFORMATION)
|
||||||
|
? "CK_UNAVAILABLE_INFORMATION"
|
||||||
|
: String.valueOf(ulSessionCount));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulMaxRwSessionCount: ");
|
||||||
|
buffer.append((ulMaxRwSessionCount == PKCS11Constants.CK_EFFECTIVELY_INFINITE)
|
||||||
|
? "CK_EFFECTIVELY_INFINITE"
|
||||||
|
: (ulMaxRwSessionCount == PKCS11Constants.CK_UNAVAILABLE_INFORMATION)
|
||||||
|
? "CK_UNAVAILABLE_INFORMATION"
|
||||||
|
: String.valueOf(ulMaxRwSessionCount));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulRwSessionCount: ");
|
||||||
|
buffer.append((ulRwSessionCount == PKCS11Constants.CK_UNAVAILABLE_INFORMATION)
|
||||||
|
? "CK_UNAVAILABLE_INFORMATION"
|
||||||
|
: String.valueOf(ulRwSessionCount));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulMaxPinLen: ");
|
||||||
|
buffer.append(String.valueOf(ulMaxPinLen));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulMinPinLen: ");
|
||||||
|
buffer.append(String.valueOf(ulMinPinLen));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulTotalPublicMemory: ");
|
||||||
|
buffer.append((ulTotalPublicMemory == PKCS11Constants.CK_UNAVAILABLE_INFORMATION)
|
||||||
|
? "CK_UNAVAILABLE_INFORMATION"
|
||||||
|
: String.valueOf(ulTotalPublicMemory));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulFreePublicMemory: ");
|
||||||
|
buffer.append((ulFreePublicMemory == PKCS11Constants.CK_UNAVAILABLE_INFORMATION)
|
||||||
|
? "CK_UNAVAILABLE_INFORMATION"
|
||||||
|
: String.valueOf(ulFreePublicMemory));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulTotalPrivateMemory: ");
|
||||||
|
buffer.append((ulTotalPrivateMemory == PKCS11Constants.CK_UNAVAILABLE_INFORMATION)
|
||||||
|
? "CK_UNAVAILABLE_INFORMATION"
|
||||||
|
: String.valueOf(ulTotalPrivateMemory));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulFreePrivateMemory: ");
|
||||||
|
buffer.append((ulFreePrivateMemory == PKCS11Constants.CK_UNAVAILABLE_INFORMATION)
|
||||||
|
? "CK_UNAVAILABLE_INFORMATION"
|
||||||
|
: String.valueOf(ulFreePrivateMemory));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hardwareVersion: ");
|
||||||
|
buffer.append(hardwareVersion.toString());
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("firmwareVersion: ");
|
||||||
|
buffer.append(firmwareVersion.toString());
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("utcTime: ");
|
||||||
|
buffer.append(new String(utcTime));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interface CK_UNLOCKMUTEX<p>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public interface CK_UNLOCKMUTEX {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method CK_UNLOCKMUTEX
|
||||||
|
*
|
||||||
|
* @param pMutex The mutex (lock) object to unlock.
|
||||||
|
* @exception PKCS11Exception
|
||||||
|
*/
|
||||||
|
public void CK_UNLOCKMUTEX(Object pMutex) throws PKCS11Exception;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_VERSION describes the version of a Cryptoki interface, a Cryptoki
|
||||||
|
* library, or an SSL implementation, or the hardware or firmware version of a
|
||||||
|
* slot or token.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_VERSION {
|
||||||
|
* CK_BYTE major;
|
||||||
|
* CK_BYTE minor;
|
||||||
|
* } CK_VERSION;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class CK_VERSION {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_BYTE major;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte major; /* integer portion of version number */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_BYTE minor;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte minor; /* 1/100ths portion of version number */
|
||||||
|
|
||||||
|
public CK_VERSION(int major, int minor) {
|
||||||
|
this.major = (byte)major;
|
||||||
|
this.minor = (byte)minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_VERSION.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_VERSION
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
|
buffer.append(major & 0xff);
|
||||||
|
buffer.append('.');
|
||||||
|
int m = minor & 0xff;
|
||||||
|
if (m < 10) {
|
||||||
|
buffer.append('0');
|
||||||
|
}
|
||||||
|
buffer.append(m);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
|
||||||
|
* CKM_X9_42_DH_DERIVE mechanism.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
|
||||||
|
* CK_X9_42_DH_KDF_TYPE kdf;
|
||||||
|
* CK_ULONG ulOtherInfoLen;
|
||||||
|
* CK_BYTE_PTR pOtherInfo;
|
||||||
|
* CK_ULONG ulPublicDataLen;
|
||||||
|
* CK_BYTE_PTR pPublicData;
|
||||||
|
* } CK_X9_42_DH1_DERIVE_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
*/
|
||||||
|
public class CK_X9_42_DH1_DERIVE_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_X9_42_DH_KDF_TYPE kdf;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long kdf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulOtherInfoLen;
|
||||||
|
* CK_BYTE_PTR pOtherInfo;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pOtherInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulPublicDataLen;
|
||||||
|
* CK_BYTE_PTR pPublicData;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pPublicData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_PKCS5_PBKD2_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("kdf: 0x");
|
||||||
|
buffer.append(Functions.toFullHexString(kdf));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pOtherInfoLen: ");
|
||||||
|
buffer.append(pOtherInfo.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pOtherInfo: ");
|
||||||
|
buffer.append(Functions.toHexString(pOtherInfo));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicDataLen: ");
|
||||||
|
buffer.append(pPublicData.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicData: ");
|
||||||
|
buffer.append(Functions.toHexString(pPublicData));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
|
||||||
|
* CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE mechanisms.<p>
|
||||||
|
* <B>PKCS#11 structure:</B>
|
||||||
|
* <PRE>
|
||||||
|
* typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
|
||||||
|
* CK_X9_42_DH_KDF_TYPE kdf;
|
||||||
|
* CK_ULONG ulOtherInfoLen;
|
||||||
|
* CK_BYTE_PTR pOtherInfo;
|
||||||
|
* CK_ULONG ulPublicDataLen;
|
||||||
|
* CK_BYTE_PTR pPublicData;
|
||||||
|
* CK_ULONG ulPrivateDataLen;
|
||||||
|
* CK_OBJECT_HANDLE hPrivateData;
|
||||||
|
* CK_ULONG ulPublicDataLen2;
|
||||||
|
* CK_BYTE_PTR pPublicData2;
|
||||||
|
* } CK_X9_42_DH2_DERIVE_PARAMS;
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
*/
|
||||||
|
public class CK_X9_42_DH2_DERIVE_PARAMS {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_X9_42_DH_KDF_TYPE kdf;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long kdf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulOtherInfoLen;
|
||||||
|
* CK_BYTE_PTR pOtherInfo;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pOtherInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulPublicDataLen;
|
||||||
|
* CK_BYTE_PTR pPublicData;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pPublicData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulPrivateDataLen;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long ulPrivateDataLen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_OBJECT_HANDLE hPrivateData;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public long hPrivateData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <B>PKCS#11:</B>
|
||||||
|
* <PRE>
|
||||||
|
* CK_ULONG ulPublicDataLen2;
|
||||||
|
* CK_BYTE_PTR pPublicData2;
|
||||||
|
* </PRE>
|
||||||
|
*/
|
||||||
|
public byte[] pPublicData2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string representation of CK_PKCS5_PBKD2_PARAMS.
|
||||||
|
*
|
||||||
|
* @return the string representation of CK_PKCS5_PBKD2_PARAMS
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("kdf: 0x");
|
||||||
|
buffer.append(Functions.toFullHexString(kdf));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pOtherInfoLen: ");
|
||||||
|
buffer.append(pOtherInfo.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pOtherInfo: ");
|
||||||
|
buffer.append(Functions.toHexString(pOtherInfo));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicDataLen: ");
|
||||||
|
buffer.append(pPublicData.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicData: ");
|
||||||
|
buffer.append(Functions.toHexString(pPublicData));
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("ulPrivateDataLen: ");
|
||||||
|
buffer.append(ulPrivateDataLen);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("hPrivateData: ");
|
||||||
|
buffer.append(hPrivateData);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicDataLen2: ");
|
||||||
|
buffer.append(pPublicData2.length);
|
||||||
|
buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
buffer.append(Constants.INDENT);
|
||||||
|
buffer.append("pPublicData2: ");
|
||||||
|
buffer.append(Functions.toHexString(pPublicData2));
|
||||||
|
//buffer.append(Constants.NEWLINE);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class holds only final static member variables that are constants
|
||||||
|
* in this package.
|
||||||
|
*
|
||||||
|
* @author Karl Scheibelhofer <Karl.Scheibelhofer@iaik.at>
|
||||||
|
* @author Martin Schlaeffer <schlaeff@sbox.tugraz.at>
|
||||||
|
*/
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
public static final String NEWLINE = System.getProperty("line.separator");
|
||||||
|
|
||||||
|
public static final String INDENT = " ";
|
||||||
|
|
||||||
|
}
|
1357
src/main/java/com/sunyard/security/pkcs11/wrapper/Functions.java
Normal file
1357
src/main/java/com/sunyard/security/pkcs11/wrapper/Functions.java
Normal file
File diff suppressed because it is too large
Load Diff
1908
src/main/java/com/sunyard/security/pkcs11/wrapper/PKCS11.java
Normal file
1908
src/main/java/com/sunyard/security/pkcs11/wrapper/PKCS11.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,320 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import static com.sunyard.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the superclass of all checked exceptions used by this package. An
|
||||||
|
* exception of this class indicates that a function call to the underlying
|
||||||
|
* PKCS#11 module returned a value not equal to CKR_OK. The application can get
|
||||||
|
* the returned value by calling getErrorCode(). A return value not equal to
|
||||||
|
* CKR_OK is the only reason for such an exception to be thrown.
|
||||||
|
* PKCS#11 defines the meaning of an error-code, which may depend on the
|
||||||
|
* context in which the error occurs.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:Karl.Scheibelhofer@iaik.at"> Karl Scheibelhofer </a>
|
||||||
|
* @invariants
|
||||||
|
*/
|
||||||
|
public class PKCS11Exception extends Exception {
|
||||||
|
private static final long serialVersionUID = 4877072363729195L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The code of the error which was the reason for this exception.
|
||||||
|
*/
|
||||||
|
protected long errorCode_;
|
||||||
|
|
||||||
|
private static final Map<Long,String> errorMap;
|
||||||
|
|
||||||
|
static {
|
||||||
|
long[] errorCodes = new long[] {
|
||||||
|
CKR_OK,
|
||||||
|
CKR_CANCEL,
|
||||||
|
CKR_HOST_MEMORY,
|
||||||
|
CKR_SLOT_ID_INVALID,
|
||||||
|
CKR_GENERAL_ERROR,
|
||||||
|
CKR_FUNCTION_FAILED,
|
||||||
|
CKR_ARGUMENTS_BAD,
|
||||||
|
CKR_NO_EVENT,
|
||||||
|
CKR_NEED_TO_CREATE_THREADS,
|
||||||
|
CKR_CANT_LOCK,
|
||||||
|
CKR_ATTRIBUTE_READ_ONLY,
|
||||||
|
CKR_ATTRIBUTE_SENSITIVE,
|
||||||
|
CKR_ATTRIBUTE_TYPE_INVALID,
|
||||||
|
CKR_ATTRIBUTE_VALUE_INVALID,
|
||||||
|
CKR_ACTION_PROHIBITED,
|
||||||
|
CKR_DATA_INVALID,
|
||||||
|
CKR_DATA_LEN_RANGE,
|
||||||
|
CKR_DEVICE_ERROR,
|
||||||
|
CKR_DEVICE_MEMORY,
|
||||||
|
CKR_DEVICE_REMOVED,
|
||||||
|
CKR_ENCRYPTED_DATA_INVALID,
|
||||||
|
CKR_ENCRYPTED_DATA_LEN_RANGE,
|
||||||
|
CKR_AEAD_DECRYPT_FAILED,
|
||||||
|
CKR_FUNCTION_CANCELED,
|
||||||
|
CKR_FUNCTION_NOT_PARALLEL,
|
||||||
|
CKR_FUNCTION_NOT_SUPPORTED,
|
||||||
|
CKR_KEY_HANDLE_INVALID,
|
||||||
|
CKR_KEY_SIZE_RANGE,
|
||||||
|
CKR_KEY_TYPE_INCONSISTENT,
|
||||||
|
CKR_KEY_NOT_NEEDED,
|
||||||
|
CKR_KEY_CHANGED,
|
||||||
|
CKR_KEY_NEEDED,
|
||||||
|
CKR_KEY_INDIGESTIBLE,
|
||||||
|
CKR_KEY_FUNCTION_NOT_PERMITTED,
|
||||||
|
CKR_KEY_NOT_WRAPPABLE,
|
||||||
|
CKR_KEY_UNEXTRACTABLE,
|
||||||
|
CKR_MECHANISM_INVALID,
|
||||||
|
CKR_MECHANISM_PARAM_INVALID,
|
||||||
|
CKR_OBJECT_HANDLE_INVALID,
|
||||||
|
CKR_OPERATION_ACTIVE,
|
||||||
|
CKR_OPERATION_NOT_INITIALIZED,
|
||||||
|
CKR_PIN_INCORRECT,
|
||||||
|
CKR_PIN_INVALID,
|
||||||
|
CKR_PIN_LEN_RANGE,
|
||||||
|
CKR_PIN_EXPIRED,
|
||||||
|
CKR_PIN_LOCKED,
|
||||||
|
CKR_SESSION_CLOSED,
|
||||||
|
CKR_SESSION_COUNT,
|
||||||
|
CKR_SESSION_HANDLE_INVALID,
|
||||||
|
CKR_SESSION_PARALLEL_NOT_SUPPORTED,
|
||||||
|
CKR_SESSION_READ_ONLY,
|
||||||
|
CKR_SESSION_EXISTS,
|
||||||
|
CKR_SESSION_READ_ONLY_EXISTS,
|
||||||
|
CKR_SESSION_READ_WRITE_SO_EXISTS,
|
||||||
|
CKR_SIGNATURE_INVALID,
|
||||||
|
CKR_SIGNATURE_LEN_RANGE,
|
||||||
|
CKR_TEMPLATE_INCOMPLETE,
|
||||||
|
CKR_TEMPLATE_INCONSISTENT,
|
||||||
|
CKR_TOKEN_NOT_PRESENT,
|
||||||
|
CKR_TOKEN_NOT_RECOGNIZED,
|
||||||
|
CKR_TOKEN_WRITE_PROTECTED,
|
||||||
|
CKR_UNWRAPPING_KEY_HANDLE_INVALID,
|
||||||
|
CKR_UNWRAPPING_KEY_SIZE_RANGE,
|
||||||
|
CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,
|
||||||
|
CKR_USER_ALREADY_LOGGED_IN,
|
||||||
|
CKR_USER_NOT_LOGGED_IN,
|
||||||
|
CKR_USER_PIN_NOT_INITIALIZED,
|
||||||
|
CKR_USER_TYPE_INVALID,
|
||||||
|
CKR_USER_ANOTHER_ALREADY_LOGGED_IN,
|
||||||
|
CKR_USER_TOO_MANY_TYPES,
|
||||||
|
CKR_WRAPPED_KEY_INVALID,
|
||||||
|
CKR_WRAPPED_KEY_LEN_RANGE,
|
||||||
|
CKR_WRAPPING_KEY_HANDLE_INVALID,
|
||||||
|
CKR_WRAPPING_KEY_SIZE_RANGE,
|
||||||
|
CKR_WRAPPING_KEY_TYPE_INCONSISTENT,
|
||||||
|
CKR_RANDOM_SEED_NOT_SUPPORTED,
|
||||||
|
CKR_RANDOM_NO_RNG,
|
||||||
|
CKR_DOMAIN_PARAMS_INVALID,
|
||||||
|
CKR_CURVE_NOT_SUPPORTED,
|
||||||
|
CKR_BUFFER_TOO_SMALL,
|
||||||
|
CKR_SAVED_STATE_INVALID,
|
||||||
|
CKR_INFORMATION_SENSITIVE,
|
||||||
|
CKR_STATE_UNSAVEABLE,
|
||||||
|
CKR_CRYPTOKI_NOT_INITIALIZED,
|
||||||
|
CKR_CRYPTOKI_ALREADY_INITIALIZED,
|
||||||
|
CKR_MUTEX_BAD,
|
||||||
|
CKR_MUTEX_NOT_LOCKED,
|
||||||
|
CKR_NEW_PIN_MODE,
|
||||||
|
CKR_NEXT_OTP,
|
||||||
|
CKR_EXCEEDED_MAX_ITERATIONS,
|
||||||
|
CKR_FIPS_SELF_TEST_FAILED,
|
||||||
|
CKR_LIBRARY_LOAD_FAILED,
|
||||||
|
CKR_PIN_TOO_WEAK,
|
||||||
|
CKR_PUBLIC_KEY_INVALID,
|
||||||
|
CKR_FUNCTION_REJECTED,
|
||||||
|
CKR_TOKEN_RESOURCE_EXCEEDED,
|
||||||
|
CKR_OPERATION_CANCEL_FAILED,
|
||||||
|
CKR_VENDOR_DEFINED,
|
||||||
|
};
|
||||||
|
String[] errorMessages = new String[] {
|
||||||
|
"CKR_OK",
|
||||||
|
"CKR_CANCEL",
|
||||||
|
"CKR_HOST_MEMORY",
|
||||||
|
"CKR_SLOT_ID_INVALID",
|
||||||
|
"CKR_GENERAL_ERROR",
|
||||||
|
"CKR_FUNCTION_FAILED",
|
||||||
|
"CKR_ARGUMENTS_BAD",
|
||||||
|
"CKR_NO_EVENT",
|
||||||
|
"CKR_NEED_TO_CREATE_THREADS",
|
||||||
|
"CKR_CANT_LOCK",
|
||||||
|
"CKR_ATTRIBUTE_READ_ONLY",
|
||||||
|
"CKR_ATTRIBUTE_SENSITIVE",
|
||||||
|
"CKR_ATTRIBUTE_TYPE_INVALID",
|
||||||
|
"CKR_ATTRIBUTE_VALUE_INVALID",
|
||||||
|
"CKR_ACTION_PROHIBITED",
|
||||||
|
"CKR_DATA_INVALID",
|
||||||
|
"CKR_DATA_LEN_RANGE",
|
||||||
|
"CKR_DEVICE_ERROR",
|
||||||
|
"CKR_DEVICE_MEMORY",
|
||||||
|
"CKR_DEVICE_REMOVED",
|
||||||
|
"CKR_ENCRYPTED_DATA_INVALID",
|
||||||
|
"CKR_ENCRYPTED_DATA_LEN_RANGE",
|
||||||
|
"CKR_AEAD_DECRYPT_FAILED",
|
||||||
|
"CKR_FUNCTION_CANCELED",
|
||||||
|
"CKR_FUNCTION_NOT_PARALLEL",
|
||||||
|
"CKR_FUNCTION_NOT_SUPPORTED",
|
||||||
|
"CKR_KEY_HANDLE_INVALID",
|
||||||
|
"CKR_KEY_SIZE_RANGE",
|
||||||
|
"CKR_KEY_TYPE_INCONSISTENT",
|
||||||
|
"CKR_KEY_NOT_NEEDED",
|
||||||
|
"CKR_KEY_CHANGED",
|
||||||
|
"CKR_KEY_NEEDED",
|
||||||
|
"CKR_KEY_INDIGESTIBLE",
|
||||||
|
"CKR_KEY_FUNCTION_NOT_PERMITTED",
|
||||||
|
"CKR_KEY_NOT_WRAPPABLE",
|
||||||
|
"CKR_KEY_UNEXTRACTABLE",
|
||||||
|
"CKR_MECHANISM_INVALID",
|
||||||
|
"CKR_MECHANISM_PARAM_INVALID",
|
||||||
|
"CKR_OBJECT_HANDLE_INVALID",
|
||||||
|
"CKR_OPERATION_ACTIVE",
|
||||||
|
"CKR_OPERATION_NOT_INITIALIZED",
|
||||||
|
"CKR_PIN_INCORRECT",
|
||||||
|
"CKR_PIN_INVALID",
|
||||||
|
"CKR_PIN_LEN_RANGE",
|
||||||
|
"CKR_PIN_EXPIRED",
|
||||||
|
"CKR_PIN_LOCKED",
|
||||||
|
"CKR_SESSION_CLOSED",
|
||||||
|
"CKR_SESSION_COUNT",
|
||||||
|
"CKR_SESSION_HANDLE_INVALID",
|
||||||
|
"CKR_SESSION_PARALLEL_NOT_SUPPORTED",
|
||||||
|
"CKR_SESSION_READ_ONLY",
|
||||||
|
"CKR_SESSION_EXISTS",
|
||||||
|
"CKR_SESSION_READ_ONLY_EXISTS",
|
||||||
|
"CKR_SESSION_READ_WRITE_SO_EXISTS",
|
||||||
|
"CKR_SIGNATURE_INVALID",
|
||||||
|
"CKR_SIGNATURE_LEN_RANGE",
|
||||||
|
"CKR_TEMPLATE_INCOMPLETE",
|
||||||
|
"CKR_TEMPLATE_INCONSISTENT",
|
||||||
|
"CKR_TOKEN_NOT_PRESENT",
|
||||||
|
"CKR_TOKEN_NOT_RECOGNIZED",
|
||||||
|
"CKR_TOKEN_WRITE_PROTECTED",
|
||||||
|
"CKR_UNWRAPPING_KEY_HANDLE_INVALID",
|
||||||
|
"CKR_UNWRAPPING_KEY_SIZE_RANGE",
|
||||||
|
"CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT",
|
||||||
|
"CKR_USER_ALREADY_LOGGED_IN",
|
||||||
|
"CKR_USER_NOT_LOGGED_IN",
|
||||||
|
"CKR_USER_PIN_NOT_INITIALIZED",
|
||||||
|
"CKR_USER_TYPE_INVALID",
|
||||||
|
"CKR_USER_ANOTHER_ALREADY_LOGGED_IN",
|
||||||
|
"CKR_USER_TOO_MANY_TYPES",
|
||||||
|
"CKR_WRAPPED_KEY_INVALID",
|
||||||
|
"CKR_WRAPPED_KEY_LEN_RANGE",
|
||||||
|
"CKR_WRAPPING_KEY_HANDLE_INVALID",
|
||||||
|
"CKR_WRAPPING_KEY_SIZE_RANGE",
|
||||||
|
"CKR_WRAPPING_KEY_TYPE_INCONSISTENT",
|
||||||
|
"CKR_RANDOM_SEED_NOT_SUPPORTED",
|
||||||
|
"CKR_RANDOM_NO_RNG",
|
||||||
|
"CKR_DOMAIN_PARAMS_INVALID",
|
||||||
|
"CKR_CURVE_NOT_SUPPORTED",
|
||||||
|
"CKR_BUFFER_TOO_SMALL",
|
||||||
|
"CKR_SAVED_STATE_INVALID",
|
||||||
|
"CKR_INFORMATION_SENSITIVE",
|
||||||
|
"CKR_STATE_UNSAVEABLE",
|
||||||
|
"CKR_CRYPTOKI_NOT_INITIALIZED",
|
||||||
|
"CKR_CRYPTOKI_ALREADY_INITIALIZED",
|
||||||
|
"CKR_MUTEX_BAD",
|
||||||
|
"CKR_MUTEX_NOT_LOCKED",
|
||||||
|
"CKR_NEW_PIN_MODE",
|
||||||
|
"CKR_NEXT_OTP",
|
||||||
|
"CKR_EXCEEDED_MAX_ITERATIONS",
|
||||||
|
"CKR_FIPS_SELF_TEST_FAILED",
|
||||||
|
"CKR_LIBRARY_LOAD_FAILED",
|
||||||
|
"CKR_PIN_TOO_WEAK",
|
||||||
|
"CKR_PUBLIC_KEY_INVALID",
|
||||||
|
"CKR_FUNCTION_REJECTED",
|
||||||
|
"CKR_TOKEN_RESOURCE_EXCEEDED",
|
||||||
|
"CKR_OPERATION_CANCEL_FAILED",
|
||||||
|
"CKR_VENDOR_DEFINED",
|
||||||
|
};
|
||||||
|
errorMap = new HashMap<Long,String>();
|
||||||
|
for (int i = 0; i < errorCodes.length; i++) {
|
||||||
|
errorMap.put(Long.valueOf(errorCodes[i]), errorMessages[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor taking the error code as defined for the CKR_* constants
|
||||||
|
* in PKCS#11.
|
||||||
|
*/
|
||||||
|
public PKCS11Exception(long errorCode) {
|
||||||
|
errorCode_ = errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method gets the corresponding text error message from
|
||||||
|
* a property file. If this file is not available, it returns the error
|
||||||
|
* code as a hex-string.
|
||||||
|
*
|
||||||
|
* @return The message or the error code; e.g. "CKR_DEVICE_ERROR" or
|
||||||
|
* "0x00000030".
|
||||||
|
* @preconditions
|
||||||
|
* @postconditions (result <> null)
|
||||||
|
*/
|
||||||
|
public String getMessage() {
|
||||||
|
String message = errorMap.get(Long.valueOf(errorCode_));
|
||||||
|
if (message == null) {
|
||||||
|
message = "0x" + Functions.toFullHexString((int)errorCode_);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the PKCS#11 error code.
|
||||||
|
*
|
||||||
|
* @return The error code; e.g. 0x00000030.
|
||||||
|
* @preconditions
|
||||||
|
* @postconditions
|
||||||
|
*/
|
||||||
|
public long getErrorCode() {
|
||||||
|
return errorCode_ ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* reserved comment block
|
||||||
|
* DO NOT REMOVE OR ALTER!
|
||||||
|
*/
|
||||||
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. The end-user documentation included with the redistribution, if any, must
|
||||||
|
* include the following acknowledgment:
|
||||||
|
*
|
||||||
|
* "This product includes software developed by IAIK of Graz University of
|
||||||
|
* Technology."
|
||||||
|
*
|
||||||
|
* Alternately, this acknowledgment may appear in the software itself, if
|
||||||
|
* and wherever such third-party acknowledgments normally appear.
|
||||||
|
*
|
||||||
|
* 4. The names "Graz University of Technology" and "IAIK of Graz University of
|
||||||
|
* Technology" must not be used to endorse or promote products derived from
|
||||||
|
* this software without prior written permission.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called
|
||||||
|
* "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
|
||||||
|
* written permission of Graz University of Technology.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||||
|
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.pkcs11.wrapper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the superclass of all runtime exception used by this library.
|
||||||
|
* For instance, Runtime exceptions occur, if an internal error in the native
|
||||||
|
* part of the wrapper occurs.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:Karl.Scheibelhofer@iaik.at"> Karl Scheibelhofer </a>
|
||||||
|
* @invariants
|
||||||
|
*/
|
||||||
|
public class PKCS11RuntimeException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = 7889842162743590564L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty constructor.
|
||||||
|
*
|
||||||
|
* @preconditions
|
||||||
|
* @postconditions
|
||||||
|
*/
|
||||||
|
public PKCS11RuntimeException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor taking a string that describes the reason of the exception
|
||||||
|
* in more detail.
|
||||||
|
*
|
||||||
|
* @param message A descrption of the reason for this exception.
|
||||||
|
* @preconditions
|
||||||
|
* @postconditions
|
||||||
|
*/
|
||||||
|
public PKCS11RuntimeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor taking an other exception to wrap.
|
||||||
|
*
|
||||||
|
* @param encapsulatedException The other exception the wrap into this.
|
||||||
|
* @preconditions
|
||||||
|
* @postconditions
|
||||||
|
*/
|
||||||
|
public PKCS11RuntimeException(Exception encapsulatedException) {
|
||||||
|
super(encapsulatedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor taking a message for this exception and an other exception to
|
||||||
|
* wrap.
|
||||||
|
*
|
||||||
|
* @param message The message giving details about the exception to ease
|
||||||
|
* debugging.
|
||||||
|
* @param encapsulatedException The other exception the wrap into this.
|
||||||
|
* @preconditions
|
||||||
|
* @postconditions
|
||||||
|
*/
|
||||||
|
public PKCS11RuntimeException(String message, Exception encapsulatedException) {
|
||||||
|
super(message, encapsulatedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
747
src/main/java/com/sunyard/security/util/CurveDB.java
Normal file
747
src/main/java/com/sunyard/security/util/CurveDB.java
Normal file
@ -0,0 +1,747 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.util;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import sun.security.util.ECUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository for well-known Elliptic Curve parameters. It is used by both
|
||||||
|
* the SunPKCS11 and SunJSSE code.
|
||||||
|
*
|
||||||
|
* @since 1.6
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
*/
|
||||||
|
public class CurveDB {
|
||||||
|
private final static int P = 1; // prime curve
|
||||||
|
private final static int B = 2; // binary curve
|
||||||
|
private final static int PD = 5; // prime curve, mark as default
|
||||||
|
private final static int BD = 6; // binary curve, mark as default
|
||||||
|
|
||||||
|
private static final Map<String,NamedCurve> oidMap =
|
||||||
|
new LinkedHashMap<String,NamedCurve>();
|
||||||
|
private static final Map<String,NamedCurve> nameMap =
|
||||||
|
new HashMap<String,NamedCurve>();
|
||||||
|
private static final Map<Integer,NamedCurve> lengthMap =
|
||||||
|
new HashMap<Integer,NamedCurve>();
|
||||||
|
|
||||||
|
private static Collection<? extends NamedCurve> specCollection;
|
||||||
|
|
||||||
|
public static final String SPLIT_PATTERN = ",|\\[|\\]";
|
||||||
|
|
||||||
|
// Used by SunECEntries
|
||||||
|
public static Collection<? extends NamedCurve>getSupportedCurves() {
|
||||||
|
return specCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a NamedCurve for the specified OID/name or null if unknown.
|
||||||
|
static NamedCurve lookup(String name) {
|
||||||
|
NamedCurve spec = oidMap.get(name);
|
||||||
|
if (spec != null) {
|
||||||
|
return spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nameMap.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return EC parameters for the specified field size. If there are known
|
||||||
|
// NIST recommended parameters for the given length, they are returned.
|
||||||
|
// Otherwise, if there are multiple matches for the given size, an
|
||||||
|
// arbitrary one is returns.
|
||||||
|
// If no parameters are known, the method returns null.
|
||||||
|
// NOTE that this method returns both prime and binary curves.
|
||||||
|
static NamedCurve lookup(int length) {
|
||||||
|
return lengthMap.get(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the given ECParameterSpec object to a NamedCurve object.
|
||||||
|
// If params does not represent a known named curve, return null.
|
||||||
|
static NamedCurve lookup(ECParameterSpec params) {
|
||||||
|
if ((params instanceof NamedCurve) || (params == null)) {
|
||||||
|
return (NamedCurve)params;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a hack to allow SunJSSE to work with 3rd party crypto
|
||||||
|
// providers for ECC and not just SunPKCS11.
|
||||||
|
// This can go away once we decide how to expose curve names in the
|
||||||
|
// public API.
|
||||||
|
// Note that it assumes that the 3rd party provider encodes named
|
||||||
|
// curves using the short form, not explicitly. If it did that, then
|
||||||
|
// the SunJSSE TLS ECC extensions are wrong, which could lead to
|
||||||
|
// interoperability problems.
|
||||||
|
int fieldSize = params.getCurve().getField().getFieldSize();
|
||||||
|
for (NamedCurve namedCurve : specCollection) {
|
||||||
|
// ECParameterSpec does not define equals, so check all the
|
||||||
|
// components ourselves.
|
||||||
|
// Quick field size check first
|
||||||
|
if (namedCurve.getCurve().getField().getFieldSize() != fieldSize) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ECUtil.equals(namedCurve, params)) {
|
||||||
|
// everything matches our named curve, return it
|
||||||
|
return namedCurve;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no match found
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BigInteger bi(String s) {
|
||||||
|
return new BigInteger(s, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void add(String name, String soid, int type, String sfield,
|
||||||
|
String a, String b, String x, String y, String n, int h,
|
||||||
|
Pattern nameSplitPattern) {
|
||||||
|
BigInteger p = bi(sfield);
|
||||||
|
ECField field;
|
||||||
|
if ((type == P) || (type == PD)) {
|
||||||
|
field = new ECFieldFp(p);
|
||||||
|
} else if ((type == B) || (type == BD)) {
|
||||||
|
field = new ECFieldF2m(p.bitLength() - 1, p);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid type: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
EllipticCurve curve = new EllipticCurve(field, bi(a), bi(b));
|
||||||
|
ECPoint g = new ECPoint(bi(x), bi(y));
|
||||||
|
|
||||||
|
NamedCurve params = new NamedCurve(name, soid, curve, g, bi(n), h);
|
||||||
|
if (oidMap.put(soid, params) != null) {
|
||||||
|
throw new RuntimeException("Duplication oid: " + soid);
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] commonNames = nameSplitPattern.split(name);
|
||||||
|
for (String commonName : commonNames) {
|
||||||
|
if (nameMap.put(commonName.trim(), params) != null) {
|
||||||
|
throw new RuntimeException("Duplication name: " + commonName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = field.getFieldSize();
|
||||||
|
if ((type == PD) || (type == BD) || (lengthMap.get(len) == null)) {
|
||||||
|
// add entry if none present for this field size or if
|
||||||
|
// the curve is marked as a default curve.
|
||||||
|
lengthMap.put(len, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Holder {
|
||||||
|
private static final Pattern nameSplitPattern = Pattern.compile(
|
||||||
|
SPLIT_PATTERN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return all the names the EC curve could be using.
|
||||||
|
static String[] getNamesByOID(String oid) {
|
||||||
|
NamedCurve nc = oidMap.get(oid);
|
||||||
|
if (nc == null) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
String[] list = Holder.nameSplitPattern.split(nc.getName());
|
||||||
|
int i = 0;
|
||||||
|
do {
|
||||||
|
list[i] = list[i].trim();
|
||||||
|
} while (++i < list.length);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
Pattern nameSplitPattern = Holder.nameSplitPattern;
|
||||||
|
|
||||||
|
/* SEC2 prime curves */
|
||||||
|
add("secp112r1", "1.3.132.0.6", P,
|
||||||
|
"DB7C2ABF62E35E668076BEAD208B",
|
||||||
|
"DB7C2ABF62E35E668076BEAD2088",
|
||||||
|
"659EF8BA043916EEDE8911702B22",
|
||||||
|
"09487239995A5EE76B55F9C2F098",
|
||||||
|
"A89CE5AF8724C0A23E0E0FF77500",
|
||||||
|
"DB7C2ABF62E35E7628DFAC6561C5",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp112r2", "1.3.132.0.7", P,
|
||||||
|
"DB7C2ABF62E35E668076BEAD208B",
|
||||||
|
"6127C24C05F38A0AAAF65C0EF02C",
|
||||||
|
"51DEF1815DB5ED74FCC34C85D709",
|
||||||
|
"4BA30AB5E892B4E1649DD0928643",
|
||||||
|
"adcd46f5882e3747def36e956e97",
|
||||||
|
"36DF0AAFD8B8D7597CA10520D04B",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp128r1", "1.3.132.0.28", P,
|
||||||
|
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
|
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||||
|
"E87579C11079F43DD824993C2CEE5ED3",
|
||||||
|
"161FF7528B899B2D0C28607CA52C5B86",
|
||||||
|
"CF5AC8395BAFEB13C02DA292DDED7A83",
|
||||||
|
"FFFFFFFE0000000075A30D1B9038A115",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp128r2", "1.3.132.0.29", P,
|
||||||
|
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
|
"D6031998D1B3BBFEBF59CC9BBFF9AEE1",
|
||||||
|
"5EEEFCA380D02919DC2C6558BB6D8A5D",
|
||||||
|
"7B6AA5D85E572983E6FB32A7CDEBC140",
|
||||||
|
"27B6916A894D3AEE7106FE805FC34B44",
|
||||||
|
"3FFFFFFF7FFFFFFFBE0024720613B5A3",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp160k1", "1.3.132.0.9", P,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
||||||
|
"0000000000000000000000000000000000000000",
|
||||||
|
"0000000000000000000000000000000000000007",
|
||||||
|
"3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
|
||||||
|
"938CF935318FDCED6BC28286531733C3F03C4FEE",
|
||||||
|
"0100000000000000000001B8FA16DFAB9ACA16B6B3",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp160r1", "1.3.132.0.8", P,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
|
||||||
|
"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
|
||||||
|
"4A96B5688EF573284664698968C38BB913CBFC82",
|
||||||
|
"23A628553168947D59DCC912042351377AC5FB32",
|
||||||
|
"0100000000000000000001F4C8F927AED3CA752257",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp160r2", "1.3.132.0.30", P,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
|
||||||
|
"B4E134D3FB59EB8BAB57274904664D5AF50388BA",
|
||||||
|
"52DCB034293A117E1F4FF11B30F7199D3144CE6D",
|
||||||
|
"FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
|
||||||
|
"0100000000000000000000351EE786A818F3A1A16B",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp192k1", "1.3.132.0.31", P,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
|
||||||
|
"000000000000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000000000003",
|
||||||
|
"DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
|
||||||
|
"9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp192r1 [NIST P-192, X9.62 prime192v1]", "1.2.840.10045.3.1.1", PD,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||||
|
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
|
||||||
|
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
|
||||||
|
"07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp224k1", "1.3.132.0.32", P,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
|
||||||
|
"00000000000000000000000000000000000000000000000000000000",
|
||||||
|
"00000000000000000000000000000000000000000000000000000005",
|
||||||
|
"A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
|
||||||
|
"7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
|
||||||
|
"010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp224r1 [NIST P-224]", "1.3.132.0.33", PD,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
|
||||||
|
"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
|
||||||
|
"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
|
||||||
|
"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp256k1", "1.3.132.0.10", P,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000007",
|
||||||
|
"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
|
||||||
|
"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp256r1 [NIST P-256, X9.62 prime256v1]", "1.2.840.10045.3.1.7", PD,
|
||||||
|
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
|
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
||||||
|
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
||||||
|
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
||||||
|
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
||||||
|
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp384r1 [NIST P-384]", "1.3.132.0.34", PD,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
||||||
|
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
||||||
|
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
||||||
|
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("secp521r1 [NIST P-521]", "1.3.132.0.35", PD,
|
||||||
|
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
|
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||||
|
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
||||||
|
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
||||||
|
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
||||||
|
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
/* ANSI X9.62 prime curves */
|
||||||
|
add("X9.62 prime192v2", "1.2.840.10045.3.1.2", P,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||||
|
"CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953",
|
||||||
|
"EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
|
||||||
|
"6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 prime192v3", "1.2.840.10045.3.1.3", P,
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||||
|
"22123DC2395A05CAA7423DAECCC94760A7D462256BD56916",
|
||||||
|
"7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
|
||||||
|
"38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
|
||||||
|
"FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 prime239v1", "1.2.840.10045.3.1.4", P,
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||||
|
"6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A",
|
||||||
|
"0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
|
||||||
|
"7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 prime239v2", "1.2.840.10045.3.1.5", P,
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||||
|
"617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C",
|
||||||
|
"38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
|
||||||
|
"5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 prime239v3", "1.2.840.10045.3.1.6", P,
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||||
|
"255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E",
|
||||||
|
"6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
|
||||||
|
"1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
|
||||||
|
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
/* SEC2 binary curves */
|
||||||
|
add("sect113r1", "1.3.132.0.4", B,
|
||||||
|
"020000000000000000000000000201",
|
||||||
|
"003088250CA6E7C7FE649CE85820F7",
|
||||||
|
"00E8BEE4D3E2260744188BE0E9C723",
|
||||||
|
"009D73616F35F4AB1407D73562C10F",
|
||||||
|
"00A52830277958EE84D1315ED31886",
|
||||||
|
"0100000000000000D9CCEC8A39E56F",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect113r2", "1.3.132.0.5", B,
|
||||||
|
"020000000000000000000000000201",
|
||||||
|
"00689918DBEC7E5A0DD6DFC0AA55C7",
|
||||||
|
"0095E9A9EC9B297BD4BF36E059184F",
|
||||||
|
"01A57A6A7B26CA5EF52FCDB8164797",
|
||||||
|
"00B3ADC94ED1FE674C06E695BABA1D",
|
||||||
|
"010000000000000108789B2496AF93",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect131r1", "1.3.132.0.22", B,
|
||||||
|
"080000000000000000000000000000010D",
|
||||||
|
"07A11B09A76B562144418FF3FF8C2570B8",
|
||||||
|
"0217C05610884B63B9C6C7291678F9D341",
|
||||||
|
"0081BAF91FDF9833C40F9C181343638399",
|
||||||
|
"078C6E7EA38C001F73C8134B1B4EF9E150",
|
||||||
|
"0400000000000000023123953A9464B54D",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect131r2", "1.3.132.0.23", B,
|
||||||
|
"080000000000000000000000000000010D",
|
||||||
|
"03E5A88919D7CAFCBF415F07C2176573B2",
|
||||||
|
"04B8266A46C55657AC734CE38F018F2192",
|
||||||
|
"0356DCD8F2F95031AD652D23951BB366A8",
|
||||||
|
"0648F06D867940A5366D9E265DE9EB240F",
|
||||||
|
"0400000000000000016954A233049BA98F",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect163k1 [NIST K-163]", "1.3.132.0.1", BD,
|
||||||
|
"0800000000000000000000000000000000000000C9",
|
||||||
|
"000000000000000000000000000000000000000001",
|
||||||
|
"000000000000000000000000000000000000000001",
|
||||||
|
"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
|
||||||
|
"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
|
||||||
|
"04000000000000000000020108A2E0CC0D99F8A5EF",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect163r1", "1.3.132.0.2", B,
|
||||||
|
"0800000000000000000000000000000000000000C9",
|
||||||
|
"07B6882CAAEFA84F9554FF8428BD88E246D2782AE2",
|
||||||
|
"0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9",
|
||||||
|
"0369979697AB43897789566789567F787A7876A654",
|
||||||
|
"00435EDB42EFAFB2989D51FEFCE3C80988F41FF883",
|
||||||
|
"03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect163r2 [NIST B-163]", "1.3.132.0.15", BD,
|
||||||
|
"0800000000000000000000000000000000000000C9",
|
||||||
|
"000000000000000000000000000000000000000001",
|
||||||
|
"020A601907B8C953CA1481EB10512F78744A3205FD",
|
||||||
|
"03F0EBA16286A2D57EA0991168D4994637E8343E36",
|
||||||
|
"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
|
||||||
|
"040000000000000000000292FE77E70C12A4234C33",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect193r1", "1.3.132.0.24", B,
|
||||||
|
"02000000000000000000000000000000000000000000008001",
|
||||||
|
"0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01",
|
||||||
|
"00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814",
|
||||||
|
"01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1",
|
||||||
|
"0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05",
|
||||||
|
"01000000000000000000000000C7F34A778F443ACC920EBA49",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect193r2", "1.3.132.0.25", B,
|
||||||
|
"02000000000000000000000000000000000000000000008001",
|
||||||
|
"0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B",
|
||||||
|
"00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE",
|
||||||
|
"00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F",
|
||||||
|
"01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C",
|
||||||
|
"010000000000000000000000015AAB561B005413CCD4EE99D5",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect233k1 [NIST K-233]", "1.3.132.0.26", BD,
|
||||||
|
"020000000000000000000000000000000000000004000000000000000001",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
|
||||||
|
"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
|
||||||
|
"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect233r1 [NIST B-233]", "1.3.132.0.27", B,
|
||||||
|
"020000000000000000000000000000000000000004000000000000000001",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
|
||||||
|
"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
|
||||||
|
"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
|
||||||
|
"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect239k1", "1.3.132.0.3", B,
|
||||||
|
"800000000000000000004000000000000000000000000000000000000001",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC",
|
||||||
|
"76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA",
|
||||||
|
"2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect283k1 [NIST K-283]", "1.3.132.0.16", BD,
|
||||||
|
"0800000000000000000000000000000000000000000000000000000000000000000010A1",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
|
||||||
|
"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
|
||||||
|
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect283r1 [NIST B-283]", "1.3.132.0.17", B,
|
||||||
|
"0800000000000000000000000000000000000000000000000000000000000000000010A1",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
|
||||||
|
"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
|
||||||
|
"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
|
||||||
|
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect409k1 [NIST K-409]", "1.3.132.0.36", BD,
|
||||||
|
"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
|
||||||
|
"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
|
||||||
|
"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect409r1 [NIST B-409]", "1.3.132.0.37", B,
|
||||||
|
"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
|
||||||
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
|
||||||
|
"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
|
||||||
|
"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
|
||||||
|
"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect571k1 [NIST K-571]", "1.3.132.0.38", BD,
|
||||||
|
"080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
|
||||||
|
"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
|
||||||
|
"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("sect571r1 [NIST B-571]", "1.3.132.0.39", B,
|
||||||
|
"080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
|
||||||
|
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
|
||||||
|
"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
|
||||||
|
"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
|
||||||
|
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
/* ANSI X9.62 binary curves */
|
||||||
|
add("X9.62 c2tnb191v1", "1.2.840.10045.3.0.5", B,
|
||||||
|
"800000000000000000000000000000000000000000000201",
|
||||||
|
"2866537B676752636A68F56554E12640276B649EF7526267",
|
||||||
|
"2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC",
|
||||||
|
"36B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D",
|
||||||
|
"765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB",
|
||||||
|
"40000000000000000000000004A20E90C39067C893BBB9A5",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2tnb191v2", "1.2.840.10045.3.0.6", B,
|
||||||
|
"800000000000000000000000000000000000000000000201",
|
||||||
|
"401028774D7777C7B7666D1366EA432071274F89FF01E718",
|
||||||
|
"0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01",
|
||||||
|
"3809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10",
|
||||||
|
"17434386626D14F3DBF01760D9213A3E1CF37AEC437D668A",
|
||||||
|
"20000000000000000000000050508CB89F652824E06B8173",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2tnb191v3", "1.2.840.10045.3.0.7", B,
|
||||||
|
"800000000000000000000000000000000000000000000201",
|
||||||
|
"6C01074756099122221056911C77D77E77A777E7E7E77FCB",
|
||||||
|
"71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8",
|
||||||
|
"375D4CE24FDE434489DE8746E71786015009E66E38A926DD",
|
||||||
|
"545A39176196575D985999366E6AD34CE0A77CD7127B06BE",
|
||||||
|
"155555555555555555555555610C0B196812BFB6288A3EA3",
|
||||||
|
6, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2tnb239v1", "1.2.840.10045.3.0.11", B,
|
||||||
|
"800000000000000000000000000000000000000000000000001000000001",
|
||||||
|
"32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
|
||||||
|
"790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
|
||||||
|
"57927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D",
|
||||||
|
"61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305",
|
||||||
|
"2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447",
|
||||||
|
4, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2tnb239v2", "1.2.840.10045.3.0.12", B,
|
||||||
|
"800000000000000000000000000000000000000000000000001000000001",
|
||||||
|
"4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F",
|
||||||
|
"5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B",
|
||||||
|
"28F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205",
|
||||||
|
"5667334C45AFF3B5A03BAD9DD75E2C71A99362567D5453F7FA6E227EC833",
|
||||||
|
"1555555555555555555555555555553C6F2885259C31E3FCDF154624522D",
|
||||||
|
6, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2tnb239v3", "1.2.840.10045.3.0.13", B,
|
||||||
|
"800000000000000000000000000000000000000000000000001000000001",
|
||||||
|
"01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F",
|
||||||
|
"6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40",
|
||||||
|
"70F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92",
|
||||||
|
"2E5A0EAF6E5E1305B9004DCE5C0ED7FE59A35608F33837C816D80B79F461",
|
||||||
|
"0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF",
|
||||||
|
0xA, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2tnb359v1", "1.2.840.10045.3.0.18", B,
|
||||||
|
"800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001",
|
||||||
|
"5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557",
|
||||||
|
"2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988",
|
||||||
|
"3C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097",
|
||||||
|
"53D7E08529547048121E9C95F3791DD804963948F34FAE7BF44EA82365DC7868FE57E4AE2DE211305A407104BD",
|
||||||
|
"01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B",
|
||||||
|
0x4C, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2tnb431r1", "1.2.840.10045.3.0.20", B,
|
||||||
|
"800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001",
|
||||||
|
"1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F",
|
||||||
|
"10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618",
|
||||||
|
"120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7",
|
||||||
|
"20D0AF8903A96F8D5FA2C255745D3C451B302C9346D9B7E485E7BCE41F6B591F3E8F6ADDCBB0BC4C2F947A7DE1A89B625D6A598B3760",
|
||||||
|
"0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91",
|
||||||
|
0x2760, nameSplitPattern);
|
||||||
|
|
||||||
|
/* ANSI X9.62 binary curves from the 1998 standard but forbidden
|
||||||
|
* in the 2005 version of the standard.
|
||||||
|
* We don't register them but leave them here for the time being in
|
||||||
|
* case we need to support them after all.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
add("X9.62 c2pnb163v1", "1.2.840.10045.3.0.1", B,
|
||||||
|
"080000000000000000000000000000000000000107",
|
||||||
|
"072546B5435234A422E0789675F432C89435DE5242",
|
||||||
|
"00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9",
|
||||||
|
"07AF69989546103D79329FCC3D74880F33BBE803CB",
|
||||||
|
"01EC23211B5966ADEA1D3F87F7EA5848AEF0B7CA9F",
|
||||||
|
"0400000000000000000001E60FC8821CC74DAEAFC1",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2pnb163v2", "1.2.840.10045.3.0.2", B,
|
||||||
|
"080000000000000000000000000000000000000107",
|
||||||
|
"0108B39E77C4B108BED981ED0E890E117C511CF072",
|
||||||
|
"0667ACEB38AF4E488C407433FFAE4F1C811638DF20",
|
||||||
|
"0024266E4EB5106D0A964D92C4860E2671DB9B6CC5",
|
||||||
|
"079F684DDF6684C5CD258B3890021B2386DFD19FC5",
|
||||||
|
"03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2pnb163v3", "1.2.840.10045.3.0.3", B,
|
||||||
|
"080000000000000000000000000000000000000107",
|
||||||
|
"07A526C63D3E25A256A007699F5447E32AE456B50E",
|
||||||
|
"03F7061798EB99E238FD6F1BF95B48FEEB4854252B",
|
||||||
|
"02F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB",
|
||||||
|
"05B935590C155E17EA48EB3FF3718B893DF59A05D0",
|
||||||
|
"03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309",
|
||||||
|
2, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2pnb176w1", "1.2.840.10045.3.0.4", B,
|
||||||
|
"0100000000000000000000000000000000080000000007",
|
||||||
|
"E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B",
|
||||||
|
"5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2",
|
||||||
|
"8D16C2866798B600F9F08BB4A8E860F3298CE04A5798",
|
||||||
|
"6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C",
|
||||||
|
"00010092537397ECA4F6145799D62B0A19CE06FE26AD",
|
||||||
|
0xFF6E, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2pnb208w1", "1.2.840.10045.3.0.10", B,
|
||||||
|
"010000000000000000000000000000000800000000000000000007",
|
||||||
|
"0000000000000000000000000000000000000000000000000000",
|
||||||
|
"C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E",
|
||||||
|
"89FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A",
|
||||||
|
"0F55B51A06E78E9AC38A035FF520D8B01781BEB1A6BB08617DE3",
|
||||||
|
"000101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D",
|
||||||
|
0xFE48, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2pnb272w1", "1.2.840.10045.3.0.16", B,
|
||||||
|
"010000000000000000000000000000000000000000000000000000010000000000000B",
|
||||||
|
"91A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20",
|
||||||
|
"7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7",
|
||||||
|
"6108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D",
|
||||||
|
"10C7695716851EEF6BA7F6872E6142FBD241B830FF5EFCACECCAB05E02005DDE9D23",
|
||||||
|
"000100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521",
|
||||||
|
0xFF06, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2pnb304w1", "1.2.840.10045.3.0.17", B,
|
||||||
|
"010000000000000000000000000000000000000000000000000000000000000000000000000807",
|
||||||
|
"FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681",
|
||||||
|
"BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE",
|
||||||
|
"197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614",
|
||||||
|
"E19FBEB76E0DA171517ECF401B50289BF014103288527A9B416A105E80260B549FDC1B92C03B",
|
||||||
|
"000101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D",
|
||||||
|
0xFE2E, nameSplitPattern);
|
||||||
|
|
||||||
|
add("X9.62 c2pnb368w1", "1.2.840.10045.3.0.19", B,
|
||||||
|
"0100000000000000000000000000000000000000000000000000000000000000000000002000000000000000000007",
|
||||||
|
"E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D",
|
||||||
|
"FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A",
|
||||||
|
"1085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F",
|
||||||
|
"7B3EB1BDDCBA62D5D8B2059B525797FC73822C59059C623A45FF3843CEE8F87CD1855ADAA81E2A0750B80FDA2310",
|
||||||
|
"00010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967",
|
||||||
|
0xFF70, nameSplitPattern);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Brainpool curves (RFC 5639)
|
||||||
|
* (Twisted curves are not included)
|
||||||
|
*/
|
||||||
|
|
||||||
|
add("brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1", P,
|
||||||
|
"E95E4A5F737059DC60DFC7AD95B3D8139515620F",
|
||||||
|
"340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
|
||||||
|
"1E589A8595423412134FAA2DBDEC95C8D8675E58",
|
||||||
|
"BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
|
||||||
|
"1667CB477A1A8EC338F94741669C976316DA6321",
|
||||||
|
"E95E4A5F737059DC60DF5991D45029409E60FC09",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", P,
|
||||||
|
"C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
|
||||||
|
"6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
|
||||||
|
"469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
|
||||||
|
"C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
|
||||||
|
"14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
|
||||||
|
"C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", P,
|
||||||
|
"D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
|
||||||
|
"68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
|
||||||
|
"2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
|
||||||
|
"0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
|
||||||
|
"58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
|
||||||
|
"D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", P,
|
||||||
|
"A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
|
||||||
|
"7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
|
||||||
|
"26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
|
||||||
|
"8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
|
||||||
|
"547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
|
||||||
|
"A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", P,
|
||||||
|
"D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
|
||||||
|
"3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
|
||||||
|
"520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
|
||||||
|
"43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
|
||||||
|
"14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
|
||||||
|
"D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", P,
|
||||||
|
"8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
|
||||||
|
"7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
|
||||||
|
"04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
|
||||||
|
"1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
|
||||||
|
"8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
|
||||||
|
"8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
add("brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", P,
|
||||||
|
"AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
|
||||||
|
"7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
|
||||||
|
"3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
|
||||||
|
"81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
|
||||||
|
"7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
|
||||||
|
"AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
|
||||||
|
1, nameSplitPattern);
|
||||||
|
|
||||||
|
specCollection = Collections.unmodifiableCollection(oidMap.values());
|
||||||
|
}
|
||||||
|
}
|
240
src/main/java/com/sunyard/security/util/ECParameters.java
Normal file
240
src/main/java/com/sunyard/security/util/ECParameters.java
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.util;
|
||||||
|
|
||||||
|
import sun.security.util.DerValue;
|
||||||
|
import sun.security.util.ECKeySizeParameterSpec;
|
||||||
|
import sun.security.util.ObjectIdentifier;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements encoding and decoding of Elliptic Curve parameters
|
||||||
|
* as specified in RFC 3279.
|
||||||
|
*
|
||||||
|
* However, only named curves are currently supported.
|
||||||
|
*
|
||||||
|
* ASN.1 from RFC 3279 follows. Note that X9.62 (2005) has added some additional
|
||||||
|
* options.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* EcpkParameters ::= CHOICE {
|
||||||
|
* ecParameters ECParameters,
|
||||||
|
* namedCurve OBJECT IDENTIFIER,
|
||||||
|
* implicitlyCA NULL }
|
||||||
|
*
|
||||||
|
* ECParameters ::= SEQUENCE {
|
||||||
|
* version ECPVer, -- version is always 1
|
||||||
|
* fieldID FieldID, -- identifies the finite field over
|
||||||
|
* -- which the curve is defined
|
||||||
|
* curve Curve, -- coefficients a and b of the
|
||||||
|
* -- elliptic curve
|
||||||
|
* base ECPoint, -- specifies the base point P
|
||||||
|
* -- on the elliptic curve
|
||||||
|
* order INTEGER, -- the order n of the base point
|
||||||
|
* cofactor INTEGER OPTIONAL -- The integer h = #E(Fq)/n
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ECPVer ::= INTEGER {ecpVer1(1)}
|
||||||
|
*
|
||||||
|
* Curve ::= SEQUENCE {
|
||||||
|
* a FieldElement,
|
||||||
|
* b FieldElement,
|
||||||
|
* seed BIT STRING OPTIONAL }
|
||||||
|
*
|
||||||
|
* FieldElement ::= OCTET STRING
|
||||||
|
*
|
||||||
|
* ECPoint ::= OCTET STRING
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @since 1.6
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
*/
|
||||||
|
public final class ECParameters extends AlgorithmParametersSpi {
|
||||||
|
|
||||||
|
// used by ECPublicKeyImpl and ECPrivateKeyImpl
|
||||||
|
public static AlgorithmParameters getAlgorithmParameters(ECParameterSpec spec)
|
||||||
|
throws InvalidKeyException {
|
||||||
|
try {
|
||||||
|
AlgorithmParameters params =
|
||||||
|
AlgorithmParameters.getInstance("EC", "SunEC");
|
||||||
|
params.init(spec);
|
||||||
|
return params;
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new InvalidKeyException("EC parameters error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The parameters these AlgorithmParameters object represents.
|
||||||
|
* Currently, it is always an instance of NamedCurve.
|
||||||
|
*/
|
||||||
|
private NamedCurve namedCurve;
|
||||||
|
|
||||||
|
// A public constructor is required by AlgorithmParameters class.
|
||||||
|
public ECParameters() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlgorithmParameterSpi methods
|
||||||
|
|
||||||
|
protected void engineInit(AlgorithmParameterSpec paramSpec)
|
||||||
|
throws InvalidParameterSpecException {
|
||||||
|
|
||||||
|
if (paramSpec == null) {
|
||||||
|
throw new InvalidParameterSpecException
|
||||||
|
("paramSpec must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paramSpec instanceof NamedCurve) {
|
||||||
|
namedCurve = (NamedCurve)paramSpec;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paramSpec instanceof ECParameterSpec) {
|
||||||
|
namedCurve = CurveDB.lookup((ECParameterSpec)paramSpec);
|
||||||
|
} else if (paramSpec instanceof ECGenParameterSpec) {
|
||||||
|
String name = ((ECGenParameterSpec)paramSpec).getName();
|
||||||
|
namedCurve = CurveDB.lookup(name);
|
||||||
|
} else if (paramSpec instanceof ECKeySizeParameterSpec) {
|
||||||
|
int keySize = ((ECKeySizeParameterSpec)paramSpec).getKeySize();
|
||||||
|
namedCurve = CurveDB.lookup(keySize);
|
||||||
|
} else {
|
||||||
|
throw new InvalidParameterSpecException
|
||||||
|
("Only ECParameterSpec and ECGenParameterSpec supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (namedCurve == null) {
|
||||||
|
throw new InvalidParameterSpecException(
|
||||||
|
"Not a supported curve: " + paramSpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(byte[] params) throws IOException {
|
||||||
|
DerValue encodedParams = new DerValue(params);
|
||||||
|
if (encodedParams.tag == DerValue.tag_ObjectId) {
|
||||||
|
ObjectIdentifier oid = encodedParams.getOID();
|
||||||
|
NamedCurve spec = CurveDB.lookup(oid.toString());
|
||||||
|
if (spec == null) {
|
||||||
|
throw new IOException("Unknown named curve: " + oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
namedCurve = spec;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException("Only named ECParameters supported");
|
||||||
|
|
||||||
|
// The code below is incomplete.
|
||||||
|
// It is left as a starting point for a complete parsing implementation.
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (encodedParams.tag != DerValue.tag_Sequence) {
|
||||||
|
throw new IOException("Unsupported EC parameters, tag: " +
|
||||||
|
encodedParams.tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
encodedParams.data.reset();
|
||||||
|
|
||||||
|
DerInputStream in = encodedParams.data;
|
||||||
|
|
||||||
|
int version = in.getInteger();
|
||||||
|
if (version != 1) {
|
||||||
|
throw new IOException("Unsupported EC parameters version: " +
|
||||||
|
version);
|
||||||
|
}
|
||||||
|
ECField field = parseField(in);
|
||||||
|
EllipticCurve curve = parseCurve(in, field);
|
||||||
|
ECPoint point = parsePoint(in, curve);
|
||||||
|
|
||||||
|
BigInteger order = in.getBigInteger();
|
||||||
|
int cofactor = 0;
|
||||||
|
|
||||||
|
if (in.available() != 0) {
|
||||||
|
cofactor = in.getInteger();
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX HashAlgorithm optional
|
||||||
|
|
||||||
|
if (encodedParams.data.available() != 0) {
|
||||||
|
throw new IOException("encoded params have " +
|
||||||
|
encodedParams.data.available() +
|
||||||
|
" extra bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ECParameterSpec(curve, point, order, cofactor);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(byte[] params, String decodingMethod)
|
||||||
|
throws IOException {
|
||||||
|
engineInit(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T extends AlgorithmParameterSpec> T
|
||||||
|
engineGetParameterSpec(Class<T> spec)
|
||||||
|
throws InvalidParameterSpecException {
|
||||||
|
|
||||||
|
if (spec.isAssignableFrom(ECParameterSpec.class)) {
|
||||||
|
return spec.cast(namedCurve);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spec.isAssignableFrom(ECGenParameterSpec.class)) {
|
||||||
|
// Ensure the name is the Object ID
|
||||||
|
String name = namedCurve.getObjectId();
|
||||||
|
return spec.cast(new ECGenParameterSpec(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spec.isAssignableFrom(ECKeySizeParameterSpec.class)) {
|
||||||
|
int keySize = namedCurve.getCurve().getField().getFieldSize();
|
||||||
|
return spec.cast(new ECKeySizeParameterSpec(keySize));
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidParameterSpecException(
|
||||||
|
"Only ECParameterSpec and ECGenParameterSpec supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] engineGetEncoded() throws IOException {
|
||||||
|
return namedCurve.getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] engineGetEncoded(String encodingMethod)
|
||||||
|
throws IOException {
|
||||||
|
return engineGetEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String engineToString() {
|
||||||
|
if (namedCurve == null) {
|
||||||
|
return "Not initialized";
|
||||||
|
}
|
||||||
|
|
||||||
|
return namedCurve.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
153
src/main/java/com/sunyard/security/util/GCMParameters.java
Normal file
153
src/main/java/com/sunyard/security/util/GCMParameters.java
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.AlgorithmParametersSpi;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
import java.security.spec.InvalidParameterSpecException;
|
||||||
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
|
import sun.misc.HexDumpEncoder;
|
||||||
|
import sun.security.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements the parameter set used with
|
||||||
|
* GCM encryption, which is defined in RFC 5084 as follows:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* GCMParameters ::= SEQUENCE {
|
||||||
|
* aes-iv OCTET STRING, -- recommended size is 12 octets
|
||||||
|
* aes-tLen AES-GCM-ICVlen DEFAULT 12 }
|
||||||
|
*
|
||||||
|
* AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16)
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @since 13
|
||||||
|
*/
|
||||||
|
public final class GCMParameters extends AlgorithmParametersSpi {
|
||||||
|
|
||||||
|
// the iv
|
||||||
|
private byte[] iv;
|
||||||
|
// the tag length in bytes
|
||||||
|
private int tLen;
|
||||||
|
|
||||||
|
public GCMParameters() {}
|
||||||
|
|
||||||
|
protected void engineInit(AlgorithmParameterSpec paramSpec)
|
||||||
|
throws InvalidParameterSpecException {
|
||||||
|
|
||||||
|
if (!(paramSpec instanceof GCMParameterSpec)) {
|
||||||
|
throw new InvalidParameterSpecException
|
||||||
|
("Inappropriate parameter specification");
|
||||||
|
}
|
||||||
|
GCMParameterSpec gps = (GCMParameterSpec) paramSpec;
|
||||||
|
// need to convert from bits to bytes for ASN.1 encoding
|
||||||
|
this.tLen = gps.getTLen()/8;
|
||||||
|
if (this.tLen < 12 || this.tLen > 16 ) {
|
||||||
|
throw new InvalidParameterSpecException
|
||||||
|
("GCM parameter parsing error: unsupported tag len: " +
|
||||||
|
this.tLen);
|
||||||
|
}
|
||||||
|
this.iv = gps.getIV();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(byte[] encoded) throws IOException {
|
||||||
|
DerValue val = new DerValue(encoded);
|
||||||
|
// check if IV or params
|
||||||
|
if (val.tag == DerValue.tag_Sequence) {
|
||||||
|
byte[] iv = val.data.getOctetString();
|
||||||
|
int tLen;
|
||||||
|
if (val.data.available() != 0) {
|
||||||
|
tLen = val.data.getInteger();
|
||||||
|
if (tLen < 12 || tLen > 16 ) {
|
||||||
|
throw new IOException
|
||||||
|
("GCM parameter parsing error: unsupported tag len: " +
|
||||||
|
tLen);
|
||||||
|
}
|
||||||
|
if (val.data.available() != 0) {
|
||||||
|
throw new IOException
|
||||||
|
("GCM parameter parsing error: extra data");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tLen = 12;
|
||||||
|
}
|
||||||
|
this.iv = iv.clone();
|
||||||
|
this.tLen = tLen;
|
||||||
|
} else {
|
||||||
|
throw new IOException("GCM parameter parsing error: no SEQ tag");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(byte[] encoded, String decodingMethod)
|
||||||
|
throws IOException {
|
||||||
|
engineInit(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T extends AlgorithmParameterSpec>
|
||||||
|
T engineGetParameterSpec(Class<T> paramSpec)
|
||||||
|
throws InvalidParameterSpecException {
|
||||||
|
|
||||||
|
if (GCMParameterSpec.class.isAssignableFrom(paramSpec)) {
|
||||||
|
return paramSpec.cast(new GCMParameterSpec(tLen * 8, iv));
|
||||||
|
} else {
|
||||||
|
throw new InvalidParameterSpecException
|
||||||
|
("Inappropriate parameter specification");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] engineGetEncoded() throws IOException {
|
||||||
|
DerOutputStream out = new DerOutputStream();
|
||||||
|
DerOutputStream bytes = new DerOutputStream();
|
||||||
|
|
||||||
|
bytes.putOctetString(iv);
|
||||||
|
// Only put non-default values
|
||||||
|
if (tLen != 12) {
|
||||||
|
bytes.putInteger(tLen);
|
||||||
|
}
|
||||||
|
out.write(DerValue.tag_Sequence, bytes);
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] engineGetEncoded(String encodingMethod)
|
||||||
|
throws IOException {
|
||||||
|
return engineGetEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a formatted string describing the parameters.
|
||||||
|
*/
|
||||||
|
protected String engineToString() {
|
||||||
|
String LINE_SEP = System.lineSeparator();
|
||||||
|
HexDumpEncoder encoder = new HexDumpEncoder();
|
||||||
|
StringBuilder sb
|
||||||
|
= new StringBuilder(LINE_SEP + " iv:" + LINE_SEP + "["
|
||||||
|
+ encoder.encodeBuffer(iv) + "]");
|
||||||
|
|
||||||
|
sb.append(LINE_SEP + "tLen(bits):" + LINE_SEP + tLen*8 + LINE_SEP);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
86
src/main/java/com/sunyard/security/util/NamedCurve.java
Normal file
86
src/main/java/com/sunyard/security/util/NamedCurve.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sunyard.security.util;
|
||||||
|
|
||||||
|
import sun.security.util.DerOutputStream;
|
||||||
|
import sun.security.util.ObjectIdentifier;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import java.security.spec.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains Elliptic Curve parameters.
|
||||||
|
*
|
||||||
|
* @since 1.6
|
||||||
|
* @author Andreas Sterbenz
|
||||||
|
*/
|
||||||
|
public final class NamedCurve extends ECParameterSpec {
|
||||||
|
|
||||||
|
// friendly name for toString() output
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
// well known OID
|
||||||
|
private final String oid;
|
||||||
|
|
||||||
|
// encoded form (as NamedCurve identified via OID)
|
||||||
|
private final byte[] encoded;
|
||||||
|
|
||||||
|
NamedCurve(String name, String oid, EllipticCurve curve,
|
||||||
|
ECPoint g, BigInteger n, int h) {
|
||||||
|
super(curve, g, n, h);
|
||||||
|
this.name = name;
|
||||||
|
this.oid = oid;
|
||||||
|
|
||||||
|
DerOutputStream out = new DerOutputStream();
|
||||||
|
|
||||||
|
try {
|
||||||
|
out.putOID(new ObjectIdentifier(oid));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Internal error", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
encoded = out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getEncoded() {
|
||||||
|
return encoded.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getObjectId() {
|
||||||
|
return oid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return name + " (" + oid + ")";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user