移植 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