移植 sunpkcs11

This commit is contained in:
cheney 2025-03-22 20:44:14 +08:00
commit e4ca64c640
82 changed files with 28607 additions and 0 deletions

41
.gitignore vendored Normal file
View 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
View 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>

View File

@ -0,0 +1,7 @@
package com.sunyard;
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}

File diff suppressed because it is too large Load Diff

View 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);
}
}

View File

@ -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;
}

View 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;
}
}

File diff suppressed because it is too large Load Diff

View 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());
}
}

View 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());
}
}

View 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;
}
}

View File

@ -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);
}
}
}

View 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());
}
}

View 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() {}
}

File diff suppressed because it is too large Load Diff

View 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);
}
}
}

View 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;
}

View 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);
}
}
}

View File

@ -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);
}
}
}

File diff suppressed because it is too large Load Diff

View 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);
}
}
}

View 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;
}
}

View 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);
}
}
}

View 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());
}
}

View File

@ -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);
}
}

View 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;
}
}

View 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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View 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();
}
}

View 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);
}

View 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;
}
}
}

View 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);
}
}
}
}

File diff suppressed because it is too large Load Diff

View 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();
}
}
}

View 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");
}
}
}

View File

@ -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();
}
}

View File

@ -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 {&nbsp;&nbsp;
* CK_ATTRIBUTE_TYPE type;&nbsp;&nbsp;
* CK_VOID_PTR pValue;&nbsp;&nbsp;
* 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;
}
}
}

View File

@ -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();
}
}

View File

@ -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 &lt;Karl.Scheibelhofer@iaik.at&gt;
* @author Martin Schlaeffer &lt;schlaeff@sbox.tugraz.at&gt;
*/
public interface CK_CREATEMUTEX {
/**
* Method CK_CREATEMUTEX
*
* @return The mutex (lock) object.
* @exception PKCS11Exception
*/
public Object CK_CREATEMUTEX() throws PKCS11Exception;
}

View File

@ -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 {&nbsp;&nbsp;
* CK_CREATEMUTEX CreateMutex;&nbsp;&nbsp;
* CK_DESTROYMUTEX DestroyMutex;&nbsp;&nbsp;
* CK_LOCKMUTEX LockMutex;&nbsp;&nbsp;
* CK_UNLOCKMUTEX UnlockMutex;&nbsp;&nbsp;
* CK_FLAGS flags;&nbsp;&nbsp;
* CK_VOID_PTR pReserved;&nbsp;&nbsp;
* } 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;
}

View 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 {&nbsp;&nbsp;
* CK_CHAR year[4];&nbsp;&nbsp;
* CK_CHAR month[2];&nbsp;&nbsp;
* CK_CHAR day[2];&nbsp;&nbsp;
* } 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();
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View 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 {&nbsp;&nbsp;
* CK_VERSION cryptokiVersion;&nbsp;&nbsp;
* CK_UTF8CHAR manufacturerID[32];&nbsp;&nbsp;
* CK_FLAGS flags;&nbsp;&nbsp;
* CK_UTF8CHAR libraryDescription[32];&nbsp;&nbsp;
* CK_VERSION libraryVersion;&nbsp;&nbsp;
* } 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() ;
}
}

View File

@ -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;
}

View File

@ -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 {&nbsp;&nbsp;
* CK_MECHANISM_TYPE mechanism;&nbsp;&nbsp;
* CK_VOID_PTR pParameter;&nbsp;&nbsp;
* CK_ULONG ulParameterLen;&nbsp;&nbsp;
* } 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() ;
}
}

View File

@ -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 {&nbsp;&nbsp;
* CK_ULONG ulMinKeySize;&nbsp;&nbsp;
* CK_ULONG ulMaxKeySize;&nbsp;&nbsp;
* CK_FLAGS flags;&nbsp;&nbsp;
* } 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() ;
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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() ;
}
}

View File

@ -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();
}
}

View File

@ -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 {&nbsp;&nbsp;
* CK_SLOT_ID slotID;&nbsp;&nbsp;
* CK_STATE state;&nbsp;&nbsp;
* CK_FLAGS flags;&nbsp;&nbsp;
* CK_ULONG ulDeviceError;&nbsp;&nbsp;
* } 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() ;
}
}

View File

@ -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 {&nbsp;&nbsp;
* CK_UTF8CHAR slotDescription[64];&nbsp;&nbsp;
* CK_UTF8CHAR manufacturerID[32];&nbsp;&nbsp;
* CK_FLAGS flags;&nbsp;&nbsp;
* CK_VERSION hardwareVersion;&nbsp;&nbsp;
* CK_VERSION firmwareVersion;&nbsp;&nbsp;
* } 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() ;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 {&nbsp;&nbsp;
* CK_UTF8CHAR label[32];&nbsp;&nbsp;
* CK_UTF8CHAR manufacturerID[32];&nbsp;&nbsp;
* CK_UTF8CHAR model[16];&nbsp;&nbsp;
* CK_CHAR serialNumber[16];&nbsp;&nbsp;
* CK_FLAGS flags;&nbsp;&nbsp;
* CK_ULONG ulMaxSessionCount;&nbsp;&nbsp;
* CK_ULONG ulSessionCount;&nbsp;&nbsp;
* CK_ULONG ulMaxRwSessionCount;&nbsp;&nbsp;
* CK_ULONG ulRwSessionCount;&nbsp;&nbsp;
* CK_ULONG ulMaxPinLen;&nbsp;&nbsp;
* CK_ULONG ulMinPinLen;&nbsp;&nbsp;
* CK_ULONG ulTotalPublicMemory;&nbsp;&nbsp;
* CK_ULONG ulFreePublicMemory;&nbsp;&nbsp;
* CK_ULONG ulTotalPrivateMemory;&nbsp;&nbsp;
* CK_ULONG ulFreePrivateMemory;&nbsp;&nbsp;
* CK_VERSION hardwareVersion;&nbsp;&nbsp;
* CK_VERSION firmwareVersion;&nbsp;&nbsp;
* CK_CHAR utcTime[16];&nbsp;&nbsp;
* } CK_TOKEN_INFO;
* &nbsp;&nbsp;
* </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() ;
}
}

View File

@ -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;
}

View File

@ -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 {&nbsp;&nbsp;
* CK_BYTE major;&nbsp;&nbsp;
* CK_BYTE minor;&nbsp;&nbsp;
* } 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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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 = " ";
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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_ ;
}
}

View File

@ -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);
}
}

View 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());
}
}

View 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();
}
}

View 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();
}
}

View 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 + ")";
}
}