6913047: Long term memory leak when using PKCS11 and JCE exceeds 32 bit process address space
Extract cryptographic keys within NSS PKCS11 software tokens for memory management purposes. Reviewed-by: valeriep
This commit is contained in:
parent
6627b03332
commit
dfcab1b85a
@ -127,6 +127,7 @@ grant codeBase "jrt:/jdk.crypto.cryptoki" {
|
|||||||
permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
|
permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
|
||||||
permission java.lang.RuntimePermission "loadLibrary.j2pkcs11";
|
permission java.lang.RuntimePermission "loadLibrary.j2pkcs11";
|
||||||
permission java.util.PropertyPermission "sun.security.pkcs11.allowSingleThreadedModules", "read";
|
permission java.util.PropertyPermission "sun.security.pkcs11.allowSingleThreadedModules", "read";
|
||||||
|
permission java.util.PropertyPermission "sun.security.pkcs11.disableKeyExtraction", "read";
|
||||||
permission java.util.PropertyPermission "os.name", "read";
|
permission java.util.PropertyPermission "os.name", "read";
|
||||||
permission java.util.PropertyPermission "os.arch", "read";
|
permission java.util.PropertyPermission "os.arch", "read";
|
||||||
permission java.util.PropertyPermission "jdk.crypto.KeyAgreement.legacyKDF", "read";
|
permission java.util.PropertyPermission "jdk.crypto.KeyAgreement.legacyKDF", "read";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -400,19 +400,35 @@ final class P11Cipher extends CipherSpi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelOperation() {
|
// reset the states to the pre-initialized values
|
||||||
if (initialized == false) {
|
// need to be called after doFinal or prior to re-init
|
||||||
return;
|
private void reset(boolean doCancel) {
|
||||||
}
|
if (!initialized) {
|
||||||
|
|
||||||
if ((session == null) || (token.explicitCancel == false)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
initialized = false;
|
||||||
try {
|
try {
|
||||||
if (session.hasObjects() == false) {
|
if (session == null) {
|
||||||
session = token.killSession(session);
|
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
if (doCancel && token.explicitCancel) {
|
||||||
|
cancelOperation();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
bytesBuffered = 0;
|
||||||
|
padBufferLen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelOperation() {
|
||||||
|
token.ensureValid();
|
||||||
|
if (session.hasObjects() == false) {
|
||||||
|
session = token.killSession(session);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
// cancel operation by finishing it
|
// cancel operation by finishing it
|
||||||
int bufLen = doFinalLength(0);
|
int bufLen = doFinalLength(0);
|
||||||
byte[] buffer = new byte[bufLen];
|
byte[] buffer = new byte[bufLen];
|
||||||
@ -421,40 +437,46 @@ final class P11Cipher extends CipherSpi {
|
|||||||
} else {
|
} else {
|
||||||
token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
|
token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
|
||||||
}
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Cancel failed", e);
|
||||||
}
|
}
|
||||||
} catch (PKCS11Exception e) {
|
|
||||||
throw new ProviderException("Cancel failed", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureInitialized() throws PKCS11Exception {
|
private void ensureInitialized() throws PKCS11Exception {
|
||||||
if (initialized == false) {
|
if (!initialized) {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize() throws PKCS11Exception {
|
private void initialize() throws PKCS11Exception {
|
||||||
if (session == null) {
|
if (p11Key == null) {
|
||||||
session = token.getOpSession();
|
throw new ProviderException(
|
||||||
|
"Operation cannot be performed without"
|
||||||
|
+ " calling engineInit first");
|
||||||
}
|
}
|
||||||
CK_MECHANISM mechParams = (blockMode == MODE_CTR?
|
token.ensureValid();
|
||||||
new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
|
long p11KeyID = p11Key.getKeyID();
|
||||||
new CK_MECHANISM(mechanism, iv));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (encrypt) {
|
if (session == null) {
|
||||||
token.p11.C_EncryptInit(session.id(), mechParams, p11Key.keyID);
|
session = token.getOpSession();
|
||||||
} else {
|
|
||||||
token.p11.C_DecryptInit(session.id(), mechParams, p11Key.keyID);
|
|
||||||
}
|
}
|
||||||
} catch (PKCS11Exception ex) {
|
CK_MECHANISM mechParams = (blockMode == MODE_CTR?
|
||||||
// release session when initialization failed
|
new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
|
||||||
|
new CK_MECHANISM(mechanism, iv));
|
||||||
|
if (encrypt) {
|
||||||
|
token.p11.C_EncryptInit(session.id(), mechParams, p11KeyID);
|
||||||
|
} else {
|
||||||
|
token.p11.C_DecryptInit(session.id(), mechParams, p11KeyID);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
session = token.releaseSession(session);
|
session = token.releaseSession(session);
|
||||||
throw ex;
|
throw e;
|
||||||
}
|
}
|
||||||
|
initialized = true;
|
||||||
bytesBuffered = 0;
|
bytesBuffered = 0;
|
||||||
padBufferLen = 0;
|
padBufferLen = 0;
|
||||||
initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if update(inLen) is called, how big does the output buffer have to be?
|
// if update(inLen) is called, how big does the output buffer have to be?
|
||||||
@ -485,18 +507,6 @@ final class P11Cipher extends CipherSpi {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the states to the pre-initialized values
|
|
||||||
private void reset(boolean doCancel) {
|
|
||||||
if (doCancel) cancelOperation();
|
|
||||||
|
|
||||||
initialized = false;
|
|
||||||
bytesBuffered = 0;
|
|
||||||
padBufferLen = 0;
|
|
||||||
if (session != null) {
|
|
||||||
session = token.releaseSession(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
|
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
|
||||||
try {
|
try {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -221,7 +221,12 @@ final class P11DHKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_PRIME),
|
new CK_ATTRIBUTE(CKA_PRIME),
|
||||||
new CK_ATTRIBUTE(CKA_BASE),
|
new CK_ATTRIBUTE(CKA_BASE),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
KeySpec spec = new DHPublicKeySpec(
|
KeySpec spec = new DHPublicKeySpec(
|
||||||
attributes[0].getBigInteger(),
|
attributes[0].getBigInteger(),
|
||||||
attributes[1].getBigInteger(),
|
attributes[1].getBigInteger(),
|
||||||
@ -243,7 +248,12 @@ final class P11DHKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_PRIME),
|
new CK_ATTRIBUTE(CKA_PRIME),
|
||||||
new CK_ATTRIBUTE(CKA_BASE),
|
new CK_ATTRIBUTE(CKA_BASE),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
KeySpec spec = new DHPrivateKeySpec(
|
KeySpec spec = new DHPrivateKeySpec(
|
||||||
attributes[0].getBigInteger(),
|
attributes[0].getBigInteger(),
|
||||||
attributes[1].getBigInteger(),
|
attributes[1].getBigInteger(),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -218,7 +218,12 @@ final class P11DSAKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_SUBPRIME),
|
new CK_ATTRIBUTE(CKA_SUBPRIME),
|
||||||
new CK_ATTRIBUTE(CKA_BASE),
|
new CK_ATTRIBUTE(CKA_BASE),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
KeySpec spec = new DSAPublicKeySpec(
|
KeySpec spec = new DSAPublicKeySpec(
|
||||||
attributes[0].getBigInteger(),
|
attributes[0].getBigInteger(),
|
||||||
attributes[1].getBigInteger(),
|
attributes[1].getBigInteger(),
|
||||||
@ -242,7 +247,12 @@ final class P11DSAKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_SUBPRIME),
|
new CK_ATTRIBUTE(CKA_SUBPRIME),
|
||||||
new CK_ATTRIBUTE(CKA_BASE),
|
new CK_ATTRIBUTE(CKA_BASE),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
KeySpec spec = new DSAPrivateKeySpec(
|
KeySpec spec = new DSAPrivateKeySpec(
|
||||||
attributes[0].getBigInteger(),
|
attributes[0].getBigInteger(),
|
||||||
attributes[1].getBigInteger(),
|
attributes[1].getBigInteger(),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -143,7 +143,8 @@ final class P11Digest extends MessageDigestSpi implements Cloneable,
|
|||||||
token.ensureValid();
|
token.ensureValid();
|
||||||
|
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
if (state == S_INIT && token.explicitCancel == true) {
|
if (state == S_INIT && token.explicitCancel == true
|
||||||
|
&& session.hasObjects() == false) {
|
||||||
session = token.killSession(session);
|
session = token.killSession(session);
|
||||||
} else {
|
} else {
|
||||||
session = token.releaseSession(session);
|
session = token.releaseSession(session);
|
||||||
@ -254,6 +255,7 @@ final class P11Digest extends MessageDigestSpi implements Cloneable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchSession();
|
fetchSession();
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
try {
|
try {
|
||||||
if (state == S_BUFFERED) {
|
if (state == S_BUFFERED) {
|
||||||
token.p11.C_DigestInit(session.id(), mechanism);
|
token.p11.C_DigestInit(session.id(), mechanism);
|
||||||
@ -264,10 +266,12 @@ final class P11Digest extends MessageDigestSpi implements Cloneable,
|
|||||||
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
|
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
|
||||||
bufOfs = 0;
|
bufOfs = 0;
|
||||||
}
|
}
|
||||||
token.p11.C_DigestKey(session.id(), p11Key.keyID);
|
token.p11.C_DigestKey(session.id(), p11KeyID);
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
engineReset();
|
engineReset();
|
||||||
throw new ProviderException("update(SecretKey) failed", e);
|
throw new ProviderException("update(SecretKey) failed", e);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -120,6 +120,7 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
|
|||||||
throw new IllegalStateException("Not initialized correctly");
|
throw new IllegalStateException("Not initialized correctly");
|
||||||
}
|
}
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long privKeyID = privateKey.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getOpSession();
|
session = token.getOpSession();
|
||||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
@ -131,8 +132,8 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
|
|||||||
attributes = token.getAttributes
|
attributes = token.getAttributes
|
||||||
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
|
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
|
||||||
long keyID = token.p11.C_DeriveKey(session.id(),
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
new CK_MECHANISM(mechanism, ckParams), privateKey.keyID,
|
new CK_MECHANISM(mechanism, ckParams), privKeyID,
|
||||||
attributes);
|
attributes);
|
||||||
attributes = new CK_ATTRIBUTE[] {
|
attributes = new CK_ATTRIBUTE[] {
|
||||||
new CK_ATTRIBUTE(CKA_VALUE)
|
new CK_ATTRIBUTE(CKA_VALUE)
|
||||||
};
|
};
|
||||||
@ -143,6 +144,7 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
|
|||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException("Could not derive key", e);
|
throw new ProviderException("Could not derive key", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
privateKey.releaseKeyID();
|
||||||
publicValue = null;
|
publicValue = null;
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
@ -182,6 +184,7 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
|
|||||||
}
|
}
|
||||||
long keyType = CKK_GENERIC_SECRET;
|
long keyType = CKK_GENERIC_SECRET;
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long privKeyID = privateKey.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getObjSession();
|
session = token.getObjSession();
|
||||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
@ -193,8 +196,8 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
|
|||||||
attributes = token.getAttributes
|
attributes = token.getAttributes
|
||||||
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
||||||
long keyID = token.p11.C_DeriveKey(session.id(),
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
new CK_MECHANISM(mechanism, ckParams), privateKey.keyID,
|
new CK_MECHANISM(mechanism, ckParams), privKeyID,
|
||||||
attributes);
|
attributes);
|
||||||
CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
|
||||||
new CK_ATTRIBUTE(CKA_VALUE_LEN),
|
new CK_ATTRIBUTE(CKA_VALUE_LEN),
|
||||||
};
|
};
|
||||||
@ -206,6 +209,7 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
|
|||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new InvalidKeyException("Could not derive key", e);
|
throw new InvalidKeyException("Could not derive key", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
privateKey.releaseKeyID();
|
||||||
publicValue = null;
|
publicValue = null;
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -290,13 +290,16 @@ final class P11ECKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_EC_POINT),
|
new CK_ATTRIBUTE(CKA_EC_POINT),
|
||||||
new CK_ATTRIBUTE(CKA_EC_PARAMS),
|
new CK_ATTRIBUTE(CKA_EC_PARAMS),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
try {
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
|
ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
|
||||||
ECPoint point = decodePoint(attributes[0].getByteArray(), params.getCurve());
|
ECPoint point = decodePoint(attributes[0].getByteArray(), params.getCurve());
|
||||||
return keySpec.cast(new ECPublicKeySpec(point, params));
|
return keySpec.cast(new ECPublicKeySpec(point, params));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new InvalidKeySpecException("Could not parse key", e);
|
throw new InvalidKeySpecException("Could not parse key", e);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
}
|
}
|
||||||
} else { // X.509 handled in superclass
|
} else { // X.509 handled in superclass
|
||||||
throw new InvalidKeySpecException("Only ECPublicKeySpec and "
|
throw new InvalidKeySpecException("Only ECPublicKeySpec and "
|
||||||
@ -312,13 +315,16 @@ final class P11ECKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_VALUE),
|
new CK_ATTRIBUTE(CKA_VALUE),
|
||||||
new CK_ATTRIBUTE(CKA_EC_PARAMS),
|
new CK_ATTRIBUTE(CKA_EC_PARAMS),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
try {
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
|
ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
|
||||||
return keySpec.cast(
|
return keySpec.cast(
|
||||||
new ECPrivateKeySpec(attributes[0].getBigInteger(), params));
|
new ECPrivateKeySpec(attributes[0].getBigInteger(), params));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new InvalidKeySpecException("Could not parse key", e);
|
throw new InvalidKeySpecException("Could not parse key", e);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
}
|
}
|
||||||
} else { // PKCS#8 handled in superclass
|
} else { // PKCS#8 handled in superclass
|
||||||
throw new InvalidKeySpecException("Only ECPrivateKeySpec "
|
throw new InvalidKeySpecException("Only ECPrivateKeySpec "
|
||||||
|
@ -29,7 +29,6 @@ import java.io.*;
|
|||||||
import java.lang.ref.*;
|
import java.lang.ref.*;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.interfaces.*;
|
import java.security.interfaces.*;
|
||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
@ -45,12 +44,15 @@ import sun.security.rsa.RSAPrivateCrtKeyImpl;
|
|||||||
import sun.security.internal.interfaces.TlsMasterSecret;
|
import sun.security.internal.interfaces.TlsMasterSecret;
|
||||||
|
|
||||||
import sun.security.pkcs11.wrapper.*;
|
import sun.security.pkcs11.wrapper.*;
|
||||||
|
|
||||||
|
import static sun.security.pkcs11.TemplateManager.O_GENERATE;
|
||||||
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
import sun.security.util.Debug;
|
import sun.security.util.Debug;
|
||||||
import sun.security.util.DerValue;
|
import sun.security.util.DerValue;
|
||||||
import sun.security.util.Length;
|
import sun.security.util.Length;
|
||||||
import sun.security.util.ECUtil;
|
import sun.security.util.ECUtil;
|
||||||
|
import sun.security.jca.JCAUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key implementation classes.
|
* Key implementation classes.
|
||||||
@ -83,23 +85,38 @@ abstract class P11Key implements Key, Length {
|
|||||||
// algorithm name, returned by getAlgorithm(), etc.
|
// algorithm name, returned by getAlgorithm(), etc.
|
||||||
final String algorithm;
|
final String algorithm;
|
||||||
|
|
||||||
// key id
|
|
||||||
final long keyID;
|
|
||||||
|
|
||||||
// effective key length of the key, e.g. 56 for a DES key
|
// effective key length of the key, e.g. 56 for a DES key
|
||||||
final int keyLength;
|
final int keyLength;
|
||||||
|
|
||||||
// flags indicating whether the key is a token object, sensitive, extractable
|
// flags indicating whether the key is a token object, sensitive, extractable
|
||||||
final boolean tokenObject, sensitive, extractable;
|
final boolean tokenObject, sensitive, extractable;
|
||||||
|
|
||||||
// phantom reference notification clean up for session keys
|
private final NativeKeyHolder keyIDHolder;
|
||||||
private final SessionKeyRef sessionKeyRef;
|
|
||||||
|
private static final boolean DISABLE_NATIVE_KEYS_EXTRACTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@systemProperty sun.security.pkcs11.disableKeyExtraction} property
|
||||||
|
* indicating whether or not cryptographic keys within tokens are
|
||||||
|
* extracted to a Java byte array for memory management purposes.
|
||||||
|
*
|
||||||
|
* Key extraction affects NSS PKCS11 library only.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static {
|
||||||
|
PrivilegedAction<String> getKeyExtractionProp =
|
||||||
|
() -> System.getProperty(
|
||||||
|
"sun.security.pkcs11.disableKeyExtraction", "false");
|
||||||
|
String disableKeyExtraction =
|
||||||
|
AccessController.doPrivileged(getKeyExtractionProp);
|
||||||
|
DISABLE_NATIVE_KEYS_EXTRACTION =
|
||||||
|
"true".equalsIgnoreCase(disableKeyExtraction);
|
||||||
|
}
|
||||||
|
|
||||||
P11Key(String type, Session session, long keyID, String algorithm,
|
P11Key(String type, Session session, long keyID, String algorithm,
|
||||||
int keyLength, CK_ATTRIBUTE[] attributes) {
|
int keyLength, CK_ATTRIBUTE[] attributes) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.token = session.token;
|
this.token = session.token;
|
||||||
this.keyID = keyID;
|
|
||||||
this.algorithm = algorithm;
|
this.algorithm = algorithm;
|
||||||
this.keyLength = keyLength;
|
this.keyLength = keyLength;
|
||||||
boolean tokenObject = false;
|
boolean tokenObject = false;
|
||||||
@ -119,11 +136,21 @@ abstract class P11Key implements Key, Length {
|
|||||||
this.tokenObject = tokenObject;
|
this.tokenObject = tokenObject;
|
||||||
this.sensitive = sensitive;
|
this.sensitive = sensitive;
|
||||||
this.extractable = extractable;
|
this.extractable = extractable;
|
||||||
if (tokenObject == false) {
|
char[] tokenLabel = this.token.tokenInfo.label;
|
||||||
sessionKeyRef = new SessionKeyRef(this, keyID, session);
|
boolean isNSS = (tokenLabel[0] == 'N' && tokenLabel[1] == 'S'
|
||||||
} else {
|
&& tokenLabel[2] == 'S');
|
||||||
sessionKeyRef = null;
|
boolean extractKeyInfo = (!DISABLE_NATIVE_KEYS_EXTRACTION && isNSS &&
|
||||||
}
|
extractable && !tokenObject);
|
||||||
|
this.keyIDHolder = new NativeKeyHolder(this, keyID, session, extractKeyInfo,
|
||||||
|
tokenObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getKeyID() {
|
||||||
|
return keyIDHolder.getKeyID();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseKeyID() {
|
||||||
|
keyIDHolder.releaseKeyID();
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCA spec
|
// see JCA spec
|
||||||
@ -208,8 +235,7 @@ abstract class P11Key implements Key, Length {
|
|||||||
token.ensureValid();
|
token.ensureValid();
|
||||||
String s1 = token.provider.getName() + " " + algorithm + " " + type
|
String s1 = token.provider.getName() + " " + algorithm + " " + type
|
||||||
+ " key, " + keyLength + " bits";
|
+ " key, " + keyLength + " bits";
|
||||||
s1 += " (id " + keyID + ", "
|
s1 += (tokenObject ? "token" : "session") + " object";
|
||||||
+ (tokenObject ? "token" : "session") + " object";
|
|
||||||
if (isPublic()) {
|
if (isPublic()) {
|
||||||
s1 += ")";
|
s1 += ")";
|
||||||
} else {
|
} else {
|
||||||
@ -241,12 +267,15 @@ abstract class P11Key implements Key, Length {
|
|||||||
|
|
||||||
void fetchAttributes(CK_ATTRIBUTE[] attributes) {
|
void fetchAttributes(CK_ATTRIBUTE[] attributes) {
|
||||||
Session tempSession = null;
|
Session tempSession = null;
|
||||||
|
long keyID = this.getKeyID();
|
||||||
try {
|
try {
|
||||||
tempSession = token.getOpSession();
|
tempSession = token.getOpSession();
|
||||||
token.p11.C_GetAttributeValue(tempSession.id(), keyID, attributes);
|
token.p11.C_GetAttributeValue(tempSession.id(), keyID,
|
||||||
|
attributes);
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
this.releaseKeyID();
|
||||||
token.releaseSession(tempSession);
|
token.releaseSession(tempSession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,7 +322,8 @@ abstract class P11Key implements Key, Length {
|
|||||||
new CK_ATTRIBUTE(CKA_SENSITIVE),
|
new CK_ATTRIBUTE(CKA_SENSITIVE),
|
||||||
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
|
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
|
||||||
});
|
});
|
||||||
return new P11SecretKey(session, keyID, algorithm, keyLength, attributes);
|
return new P11SecretKey(session, keyID, algorithm, keyLength,
|
||||||
|
attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
|
static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
|
||||||
@ -303,8 +333,9 @@ abstract class P11Key implements Key, Length {
|
|||||||
new CK_ATTRIBUTE(CKA_SENSITIVE),
|
new CK_ATTRIBUTE(CKA_SENSITIVE),
|
||||||
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
|
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
|
||||||
});
|
});
|
||||||
return new P11TlsMasterSecretKey
|
return new P11TlsMasterSecretKey(
|
||||||
(session, keyID, algorithm, keyLength, attributes, major, minor);
|
session, keyID, algorithm, keyLength, attributes, major,
|
||||||
|
minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we assume that all components of public keys are always accessible
|
// we assume that all components of public keys are always accessible
|
||||||
@ -312,17 +343,17 @@ abstract class P11Key implements Key, Length {
|
|||||||
int keyLength, CK_ATTRIBUTE[] attributes) {
|
int keyLength, CK_ATTRIBUTE[] attributes) {
|
||||||
switch (algorithm) {
|
switch (algorithm) {
|
||||||
case "RSA":
|
case "RSA":
|
||||||
return new P11RSAPublicKey
|
return new P11RSAPublicKey(session, keyID, algorithm,
|
||||||
(session, keyID, algorithm, keyLength, attributes);
|
keyLength, attributes);
|
||||||
case "DSA":
|
case "DSA":
|
||||||
return new P11DSAPublicKey
|
return new P11DSAPublicKey(session, keyID, algorithm,
|
||||||
(session, keyID, algorithm, keyLength, attributes);
|
keyLength, attributes);
|
||||||
case "DH":
|
case "DH":
|
||||||
return new P11DHPublicKey
|
return new P11DHPublicKey(session, keyID, algorithm,
|
||||||
(session, keyID, algorithm, keyLength, attributes);
|
keyLength, attributes);
|
||||||
case "EC":
|
case "EC":
|
||||||
return new P11ECPublicKey
|
return new P11ECPublicKey(session, keyID, algorithm,
|
||||||
(session, keyID, algorithm, keyLength, attributes);
|
keyLength, attributes);
|
||||||
default:
|
default:
|
||||||
throw new ProviderException
|
throw new ProviderException
|
||||||
("Unknown public key algorithm " + algorithm);
|
("Unknown public key algorithm " + algorithm);
|
||||||
@ -367,21 +398,21 @@ abstract class P11Key implements Key, Length {
|
|||||||
crtKey = false;
|
crtKey = false;
|
||||||
}
|
}
|
||||||
if (crtKey) {
|
if (crtKey) {
|
||||||
return new P11RSAPrivateKey
|
return new P11RSAPrivateKey(session, keyID, algorithm,
|
||||||
(session, keyID, algorithm, keyLength, attributes, attrs2);
|
keyLength, attributes, attrs2);
|
||||||
} else {
|
} else {
|
||||||
return new P11RSAPrivateNonCRTKey
|
return new P11RSAPrivateNonCRTKey(session, keyID,
|
||||||
(session, keyID, algorithm, keyLength, attributes);
|
algorithm, keyLength, attributes);
|
||||||
}
|
}
|
||||||
case "DSA":
|
case "DSA":
|
||||||
return new P11DSAPrivateKey
|
return new P11DSAPrivateKey(session, keyID, algorithm,
|
||||||
(session, keyID, algorithm, keyLength, attributes);
|
keyLength, attributes);
|
||||||
case "DH":
|
case "DH":
|
||||||
return new P11DHPrivateKey
|
return new P11DHPrivateKey(session, keyID, algorithm,
|
||||||
(session, keyID, algorithm, keyLength, attributes);
|
keyLength, attributes);
|
||||||
case "EC":
|
case "EC":
|
||||||
return new P11ECPrivateKey
|
return new P11ECPrivateKey(session, keyID, algorithm,
|
||||||
(session, keyID, algorithm, keyLength, attributes);
|
keyLength, attributes);
|
||||||
default:
|
default:
|
||||||
throw new ProviderException
|
throw new ProviderException
|
||||||
("Unknown private key algorithm " + algorithm);
|
("Unknown private key algorithm " + algorithm);
|
||||||
@ -435,17 +466,19 @@ abstract class P11Key implements Key, Length {
|
|||||||
b = encoded;
|
b = encoded;
|
||||||
if (b == null) {
|
if (b == null) {
|
||||||
Session tempSession = null;
|
Session tempSession = null;
|
||||||
|
long keyID = this.getKeyID();
|
||||||
try {
|
try {
|
||||||
tempSession = token.getOpSession();
|
tempSession = token.getOpSession();
|
||||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
new CK_ATTRIBUTE(CKA_VALUE),
|
new CK_ATTRIBUTE(CKA_VALUE),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue
|
token.p11.C_GetAttributeValue
|
||||||
(tempSession.id(), keyID, attributes);
|
(tempSession.id(), keyID, attributes);
|
||||||
b = attributes[0].getByteArray();
|
b = attributes[0].getByteArray();
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
this.releaseKeyID();
|
||||||
token.releaseSession(tempSession);
|
token.releaseSession(tempSession);
|
||||||
}
|
}
|
||||||
encoded = b;
|
encoded = b;
|
||||||
@ -1100,6 +1133,153 @@ abstract class P11Key implements Key, Length {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class NativeKeyHolder {
|
||||||
|
|
||||||
|
private static long nativeKeyWrapperKeyID = 0;
|
||||||
|
private static CK_MECHANISM nativeKeyWrapperMechanism = null;
|
||||||
|
|
||||||
|
private final P11Key p11Key;
|
||||||
|
private final byte[] nativeKeyInfo;
|
||||||
|
|
||||||
|
// destroyed and recreated when refCount toggles to 1
|
||||||
|
private long keyID;
|
||||||
|
|
||||||
|
private boolean isTokenObject;
|
||||||
|
|
||||||
|
// phantom reference notification clean up for session keys
|
||||||
|
private SessionKeyRef ref;
|
||||||
|
|
||||||
|
private int refCount;
|
||||||
|
|
||||||
|
NativeKeyHolder(P11Key p11Key, long keyID, Session keySession,
|
||||||
|
boolean extractKeyInfo, boolean isTokenObject) {
|
||||||
|
this.p11Key = p11Key;
|
||||||
|
this.keyID = keyID;
|
||||||
|
this.refCount = -1;
|
||||||
|
byte[] ki = null;
|
||||||
|
if (isTokenObject) {
|
||||||
|
this.ref = null;
|
||||||
|
} else {
|
||||||
|
this.ref = new SessionKeyRef(p11Key, keyID, keySession);
|
||||||
|
|
||||||
|
// Try extracting key info, if any error, disable it
|
||||||
|
Token token = p11Key.token;
|
||||||
|
if (extractKeyInfo) {
|
||||||
|
try {
|
||||||
|
if (p11Key.sensitive && nativeKeyWrapperKeyID == 0) {
|
||||||
|
synchronized(NativeKeyHolder.class) {
|
||||||
|
// Create a global wrapping/unwrapping key
|
||||||
|
CK_ATTRIBUTE[] wrappingAttributes = token.getAttributes
|
||||||
|
(O_GENERATE, CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] {
|
||||||
|
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
||||||
|
new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3),
|
||||||
|
});
|
||||||
|
Session wrappingSession = null;
|
||||||
|
try {
|
||||||
|
wrappingSession = token.getObjSession();
|
||||||
|
nativeKeyWrapperKeyID = token.p11.C_GenerateKey
|
||||||
|
(wrappingSession.id(),
|
||||||
|
new CK_MECHANISM(CKM_AES_KEY_GEN),
|
||||||
|
wrappingAttributes);
|
||||||
|
byte[] iv = new byte[16];
|
||||||
|
JCAUtil.getSecureRandom().nextBytes(iv);
|
||||||
|
nativeKeyWrapperMechanism = new CK_MECHANISM
|
||||||
|
(CKM_AES_CBC_PAD, iv);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// best effort
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(wrappingSession);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Session opSession = null;
|
||||||
|
try {
|
||||||
|
opSession = token.getOpSession();
|
||||||
|
ki = p11Key.token.p11.getNativeKeyInfo(opSession.id(),
|
||||||
|
keyID, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// best effort
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(opSession);
|
||||||
|
}
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// best effort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.nativeKeyInfo = ((ki == null || ki.length == 0)? null : ki);
|
||||||
|
}
|
||||||
|
|
||||||
|
long getKeyID() throws ProviderException {
|
||||||
|
if (this.nativeKeyInfo != null) {
|
||||||
|
synchronized(this.nativeKeyInfo) {
|
||||||
|
if (this.refCount == -1) {
|
||||||
|
this.refCount = 0;
|
||||||
|
}
|
||||||
|
int cnt = (this.refCount)++;
|
||||||
|
if (keyID == 0) {
|
||||||
|
if (cnt != 0) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Error: null keyID with non-zero refCount " + cnt);
|
||||||
|
}
|
||||||
|
if (this.ref != null) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Error: null keyID with non-null session ref");
|
||||||
|
}
|
||||||
|
Token token = p11Key.token;
|
||||||
|
// Create keyID using nativeKeyInfo
|
||||||
|
Session session = null;
|
||||||
|
try {
|
||||||
|
session = token.getObjSession();
|
||||||
|
this.keyID = token.p11.createNativeKey(session.id(),
|
||||||
|
nativeKeyInfo, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism);
|
||||||
|
this.ref = new SessionKeyRef(p11Key, this.keyID, session);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
this.refCount--;
|
||||||
|
throw new ProviderException("Error recreating native key", e);
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(session);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cnt < 0) {
|
||||||
|
throw new RuntimeException("ERROR: negative refCount");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keyID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseKeyID() {
|
||||||
|
if (this.nativeKeyInfo != null) {
|
||||||
|
synchronized(this.nativeKeyInfo) {
|
||||||
|
if (this.refCount == -1) {
|
||||||
|
throw new RuntimeException("Error: miss match getKeyID call");
|
||||||
|
}
|
||||||
|
int cnt = --(this.refCount);
|
||||||
|
if (cnt == 0) {
|
||||||
|
// destroy
|
||||||
|
if (this.keyID == 0) {
|
||||||
|
throw new RuntimeException("ERROR: null keyID can't be destroyed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.ref == null) {
|
||||||
|
throw new RuntimeException("ERROR: null session ref can't be disposed");
|
||||||
|
}
|
||||||
|
// destroy
|
||||||
|
this.keyID = 0;
|
||||||
|
this.ref = this.ref.dispose();
|
||||||
|
} else {
|
||||||
|
if (cnt < 0) {
|
||||||
|
// should never happen as we start count at 1 and pair get/release calls
|
||||||
|
throw new RuntimeException("wrong refCount value: " + cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: Must use PhantomReference here and not WeakReference
|
* NOTE: Must use PhantomReference here and not WeakReference
|
||||||
* otherwise the key maybe cleared before other objects which
|
* otherwise the key maybe cleared before other objects which
|
||||||
@ -1117,64 +1297,50 @@ final class SessionKeyRef extends PhantomReference<P11Key>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void drainRefQueueBounded() {
|
private static void drainRefQueueBounded() {
|
||||||
Session sess = null;
|
|
||||||
Token tkn = null;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
SessionKeyRef next = (SessionKeyRef) refQueue.poll();
|
SessionKeyRef next = (SessionKeyRef) refQueue.poll();
|
||||||
if (next == null) {
|
if (next == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the token is still valid, try to remove the object
|
|
||||||
if (next.session.token.isValid()) {
|
|
||||||
// If this key's token is the same as the previous key, the
|
|
||||||
// same session can be used for C_DestroyObject.
|
|
||||||
try {
|
|
||||||
if (next.session.token != tkn || sess == null) {
|
|
||||||
// Release session if not using previous token
|
|
||||||
if (tkn != null && sess != null) {
|
|
||||||
tkn.releaseSession(sess);
|
|
||||||
sess = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
tkn = next.session.token;
|
|
||||||
sess = tkn.getOpSession();
|
|
||||||
}
|
|
||||||
next.disposeNative(sess);
|
|
||||||
} catch (PKCS11Exception e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Regardless of native results, dispose of java references
|
|
||||||
next.dispose();
|
next.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tkn != null && sess != null) {
|
|
||||||
tkn.releaseSession(sess);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle to the native key
|
// handle to the native key and the session it is generated under
|
||||||
private long keyID;
|
private final long keyID;
|
||||||
private Session session;
|
private final Session session;
|
||||||
|
|
||||||
SessionKeyRef(P11Key key , long keyID, Session session) {
|
SessionKeyRef(P11Key p11Key, long keyID, Session session) {
|
||||||
super(key, refQueue);
|
super(p11Key, refQueue);
|
||||||
|
if (session == null) {
|
||||||
|
throw new ProviderException("key must be associated with a session");
|
||||||
|
}
|
||||||
this.keyID = keyID;
|
this.keyID = keyID;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.session.addObject();
|
this.session.addObject();
|
||||||
|
|
||||||
refList.add(this);
|
refList.add(this);
|
||||||
drainRefQueueBounded();
|
drainRefQueueBounded();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disposeNative(Session s) throws PKCS11Exception {
|
SessionKeyRef dispose() {
|
||||||
session.token.p11.C_DestroyObject(s.id(), keyID);
|
Token token = session.token;
|
||||||
}
|
// If the token is still valid, try to remove the key object
|
||||||
|
if (token.isValid()) {
|
||||||
private void dispose() {
|
Session s = null;
|
||||||
|
try {
|
||||||
|
s = token.getOpSession();
|
||||||
|
token.p11.C_DestroyObject(s.id(), keyID);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
// best effort
|
||||||
|
} finally {
|
||||||
|
token.releaseSession(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
refList.remove(this);
|
refList.remove(this);
|
||||||
this.clear();
|
this.clear();
|
||||||
session.removeObject();
|
session.removeObject();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(SessionKeyRef other) {
|
public int compareTo(SessionKeyRef other) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -201,6 +201,7 @@ final class P11KeyAgreement extends KeyAgreementSpi {
|
|||||||
throw new IllegalStateException("Not initialized correctly");
|
throw new IllegalStateException("Not initialized correctly");
|
||||||
}
|
}
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long privKeyID = privateKey.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getOpSession();
|
session = token.getOpSession();
|
||||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
@ -210,8 +211,9 @@ final class P11KeyAgreement extends KeyAgreementSpi {
|
|||||||
attributes = token.getAttributes
|
attributes = token.getAttributes
|
||||||
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
|
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
|
||||||
long keyID = token.p11.C_DeriveKey(session.id(),
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
new CK_MECHANISM(mechanism, publicValue), privateKey.keyID,
|
new CK_MECHANISM(mechanism, publicValue), privKeyID,
|
||||||
attributes);
|
attributes);
|
||||||
|
|
||||||
attributes = new CK_ATTRIBUTE[] {
|
attributes = new CK_ATTRIBUTE[] {
|
||||||
new CK_ATTRIBUTE(CKA_VALUE)
|
new CK_ATTRIBUTE(CKA_VALUE)
|
||||||
};
|
};
|
||||||
@ -237,6 +239,7 @@ final class P11KeyAgreement extends KeyAgreementSpi {
|
|||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException("Could not derive key", e);
|
throw new ProviderException("Could not derive key", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
privateKey.releaseKeyID();
|
||||||
publicValue = null;
|
publicValue = null;
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
@ -325,6 +328,7 @@ final class P11KeyAgreement extends KeyAgreementSpi {
|
|||||||
}
|
}
|
||||||
long keyType = CKK_GENERIC_SECRET;
|
long keyType = CKK_GENERIC_SECRET;
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long privKeyID = privateKey.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getObjSession();
|
session = token.getObjSession();
|
||||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
||||||
@ -334,8 +338,8 @@ final class P11KeyAgreement extends KeyAgreementSpi {
|
|||||||
attributes = token.getAttributes
|
attributes = token.getAttributes
|
||||||
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
||||||
long keyID = token.p11.C_DeriveKey(session.id(),
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
new CK_MECHANISM(mechanism, publicValue), privateKey.keyID,
|
new CK_MECHANISM(mechanism, publicValue), privKeyID,
|
||||||
attributes);
|
attributes);
|
||||||
CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
|
||||||
new CK_ATTRIBUTE(CKA_VALUE_LEN),
|
new CK_ATTRIBUTE(CKA_VALUE_LEN),
|
||||||
};
|
};
|
||||||
@ -359,6 +363,7 @@ final class P11KeyAgreement extends KeyAgreementSpi {
|
|||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new InvalidKeyException("Could not derive key", e);
|
throw new InvalidKeyException("Could not derive key", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
privateKey.releaseKeyID();
|
||||||
publicValue = null;
|
publicValue = null;
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1485,6 +1485,7 @@ final class P11KeyStore extends KeyStoreSpi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// retrieves the native key handle and either update it directly or make a copy
|
||||||
private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
|
private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
|
||||||
throws PKCS11Exception {
|
throws PKCS11Exception {
|
||||||
|
|
||||||
@ -1492,23 +1493,22 @@ final class P11KeyStore extends KeyStoreSpi {
|
|||||||
// if session key, convert to token key.
|
// if session key, convert to token key.
|
||||||
|
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long keyID = key.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getOpSession();
|
session = token.getOpSession();
|
||||||
if (key.tokenObject == true) {
|
if (key.tokenObject == true) {
|
||||||
|
|
||||||
// token key - set new CKA_ID
|
// token key - set new CKA_ID
|
||||||
|
|
||||||
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
||||||
new CK_ATTRIBUTE(CKA_ID, alias) };
|
new CK_ATTRIBUTE(CKA_ID, alias) };
|
||||||
token.p11.C_SetAttributeValue
|
token.p11.C_SetAttributeValue
|
||||||
(session.id(), key.keyID, attrs);
|
(session.id(), keyID, attrs);
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
debug.println("updateP11Pkey set new alias [" +
|
debug.println("updateP11Pkey set new alias [" +
|
||||||
alias +
|
alias +
|
||||||
"] for key entry");
|
"] for key entry");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// session key - convert to token key and set CKA_ID
|
// session key - convert to token key and set CKA_ID
|
||||||
|
|
||||||
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
||||||
@ -1518,7 +1518,8 @@ final class P11KeyStore extends KeyStoreSpi {
|
|||||||
if (attribute != null) {
|
if (attribute != null) {
|
||||||
attrs = addAttribute(attrs, attribute);
|
attrs = addAttribute(attrs, attribute);
|
||||||
}
|
}
|
||||||
token.p11.C_CopyObject(session.id(), key.keyID, attrs);
|
// creates a new token key with the desired CKA_ID
|
||||||
|
token.p11.C_CopyObject(session.id(), keyID, attrs);
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
debug.println("updateP11Pkey copied private session key " +
|
debug.println("updateP11Pkey copied private session key " +
|
||||||
"for [" +
|
"for [" +
|
||||||
@ -1528,6 +1529,7 @@ final class P11KeyStore extends KeyStoreSpi {
|
|||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
|
key.releaseKeyID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1894,10 +1896,12 @@ final class P11KeyStore extends KeyStoreSpi {
|
|||||||
return attrs;
|
return attrs;
|
||||||
}
|
}
|
||||||
String alg = privateKey.getAlgorithm();
|
String alg = privateKey.getAlgorithm();
|
||||||
if (id && alg.equals("RSA") && (publicKey instanceof RSAPublicKey)) {
|
if (alg.equals("RSA") && (publicKey instanceof RSAPublicKey)) {
|
||||||
|
if (id) {
|
||||||
|
BigInteger n = ((RSAPublicKey)publicKey).getModulus();
|
||||||
|
attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(n)));
|
||||||
|
}
|
||||||
// CKA_NETSCAPE_DB not needed for RSA public keys
|
// CKA_NETSCAPE_DB not needed for RSA public keys
|
||||||
BigInteger n = ((RSAPublicKey)publicKey).getModulus();
|
|
||||||
attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(n)));
|
|
||||||
} else if (alg.equals("DSA") && (publicKey instanceof DSAPublicKey)) {
|
} else if (alg.equals("DSA") && (publicKey instanceof DSAPublicKey)) {
|
||||||
BigInteger y = ((DSAPublicKey)publicKey).getY();
|
BigInteger y = ((DSAPublicKey)publicKey).getY();
|
||||||
if (id) {
|
if (id) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
package sun.security.pkcs11;
|
package sun.security.pkcs11;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
@ -54,27 +53,12 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
|||||||
*/
|
*/
|
||||||
final class P11Mac extends MacSpi {
|
final class P11Mac extends MacSpi {
|
||||||
|
|
||||||
/* unitialized, all fields except session have arbitrary values */
|
|
||||||
private final static int S_UNINIT = 1;
|
|
||||||
|
|
||||||
/* session initialized, no data processed yet */
|
|
||||||
private final static int S_RESET = 2;
|
|
||||||
|
|
||||||
/* session initialized, data processed */
|
|
||||||
private final static int S_UPDATE = 3;
|
|
||||||
|
|
||||||
/* transitional state after doFinal() before we go to S_UNINIT */
|
|
||||||
private final static int S_DOFINAL = 4;
|
|
||||||
|
|
||||||
// token instance
|
// token instance
|
||||||
private final Token token;
|
private final Token token;
|
||||||
|
|
||||||
// algorithm name
|
// algorithm name
|
||||||
private final String algorithm;
|
private final String algorithm;
|
||||||
|
|
||||||
// mechanism id
|
|
||||||
private final long mechanism;
|
|
||||||
|
|
||||||
// mechanism object
|
// mechanism object
|
||||||
private final CK_MECHANISM ckMechanism;
|
private final CK_MECHANISM ckMechanism;
|
||||||
|
|
||||||
@ -87,8 +71,8 @@ final class P11Mac extends MacSpi {
|
|||||||
// associated session, if any
|
// associated session, if any
|
||||||
private Session session;
|
private Session session;
|
||||||
|
|
||||||
// state, one of S_* above
|
// initialization status
|
||||||
private int state;
|
private boolean initialized;
|
||||||
|
|
||||||
// one byte buffer for the update(byte) method, initialized on demand
|
// one byte buffer for the update(byte) method, initialized on demand
|
||||||
private byte[] oneByte;
|
private byte[] oneByte;
|
||||||
@ -98,7 +82,6 @@ final class P11Mac extends MacSpi {
|
|||||||
super();
|
super();
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.algorithm = algorithm;
|
this.algorithm = algorithm;
|
||||||
this.mechanism = mechanism;
|
|
||||||
Long params = null;
|
Long params = null;
|
||||||
switch ((int)mechanism) {
|
switch ((int)mechanism) {
|
||||||
case (int)CKM_MD5_HMAC:
|
case (int)CKM_MD5_HMAC:
|
||||||
@ -131,47 +114,65 @@ final class P11Mac extends MacSpi {
|
|||||||
throw new ProviderException("Unknown mechanism: " + mechanism);
|
throw new ProviderException("Unknown mechanism: " + mechanism);
|
||||||
}
|
}
|
||||||
ckMechanism = new CK_MECHANISM(mechanism, params);
|
ckMechanism = new CK_MECHANISM(mechanism, params);
|
||||||
state = S_UNINIT;
|
|
||||||
initialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureInitialized() throws PKCS11Exception {
|
// reset the states to the pre-initialized values
|
||||||
token.ensureValid();
|
private void reset(boolean doCancel) {
|
||||||
if (state == S_UNINIT) {
|
if (!initialized) {
|
||||||
initialize();
|
return;
|
||||||
|
}
|
||||||
|
initialized = false;
|
||||||
|
try {
|
||||||
|
if (session == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (doCancel && token.explicitCancel) {
|
||||||
|
cancelOperation();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelOperation() {
|
private void cancelOperation() {
|
||||||
token.ensureValid();
|
token.ensureValid();
|
||||||
if (state == S_UNINIT) {
|
if (session.hasObjects() == false) {
|
||||||
|
session = token.killSession(session);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
token.p11.C_SignFinal(session.id(), 0);
|
||||||
|
} catch (PKCS11Exception e) {
|
||||||
|
throw new ProviderException("Cancel failed", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
state = S_UNINIT;
|
}
|
||||||
if ((session == null) || (token.explicitCancel == false)) {
|
|
||||||
return;
|
private void ensureInitialized() throws PKCS11Exception {
|
||||||
}
|
if (!initialized) {
|
||||||
try {
|
initialize();
|
||||||
token.p11.C_SignFinal(session.id(), 0);
|
|
||||||
} catch (PKCS11Exception e) {
|
|
||||||
throw new ProviderException("Cancel failed", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize() throws PKCS11Exception {
|
private void initialize() throws PKCS11Exception {
|
||||||
if (state == S_RESET) {
|
if (p11Key == null) {
|
||||||
return;
|
throw new ProviderException(
|
||||||
|
"Operation cannot be performed without calling engineInit first");
|
||||||
}
|
}
|
||||||
if (session == null) {
|
token.ensureValid();
|
||||||
session = token.getOpSession();
|
long p11KeyID = p11Key.getKeyID();
|
||||||
}
|
try {
|
||||||
if (p11Key != null) {
|
if (session == null) {
|
||||||
token.p11.C_SignInit
|
session = token.getOpSession();
|
||||||
(session.id(), ckMechanism, p11Key.keyID);
|
}
|
||||||
state = S_RESET;
|
token.p11.C_SignInit(session.id(), ckMechanism, p11KeyID);
|
||||||
} else {
|
} catch (PKCS11Exception e) {
|
||||||
state = S_UNINIT;
|
p11Key.releaseKeyID();
|
||||||
|
session = token.releaseSession(session);
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
@ -181,18 +182,7 @@ final class P11Mac extends MacSpi {
|
|||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected void engineReset() {
|
protected void engineReset() {
|
||||||
// the framework insists on calling reset() after doFinal(),
|
reset(true);
|
||||||
// but we prefer to take care of reinitialization ourselves
|
|
||||||
if (state == S_DOFINAL) {
|
|
||||||
state = S_UNINIT;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cancelOperation();
|
|
||||||
try {
|
|
||||||
initialize();
|
|
||||||
} catch (PKCS11Exception e) {
|
|
||||||
throw new ProviderException("reset() failed, ", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
@ -202,7 +192,7 @@ final class P11Mac extends MacSpi {
|
|||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("Parameters not supported");
|
("Parameters not supported");
|
||||||
}
|
}
|
||||||
cancelOperation();
|
reset(true);
|
||||||
p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm);
|
p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm);
|
||||||
try {
|
try {
|
||||||
initialize();
|
initialize();
|
||||||
@ -215,13 +205,12 @@ final class P11Mac extends MacSpi {
|
|||||||
protected byte[] engineDoFinal() {
|
protected byte[] engineDoFinal() {
|
||||||
try {
|
try {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
byte[] mac = token.p11.C_SignFinal(session.id(), 0);
|
return token.p11.C_SignFinal(session.id(), 0);
|
||||||
state = S_DOFINAL;
|
|
||||||
return mac;
|
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
|
reset(true);
|
||||||
throw new ProviderException("doFinal() failed", e);
|
throw new ProviderException("doFinal() failed", e);
|
||||||
} finally {
|
} finally {
|
||||||
session = token.releaseSession(session);
|
reset(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +228,6 @@ final class P11Mac extends MacSpi {
|
|||||||
try {
|
try {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
|
token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
|
||||||
state = S_UPDATE;
|
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException("update() failed", e);
|
throw new ProviderException("update() failed", e);
|
||||||
}
|
}
|
||||||
@ -261,7 +249,6 @@ final class P11Mac extends MacSpi {
|
|||||||
int ofs = byteBuffer.position();
|
int ofs = byteBuffer.position();
|
||||||
token.p11.C_SignUpdate(session.id(), addr + ofs, null, 0, len);
|
token.p11.C_SignUpdate(session.id(), addr + ofs, null, 0, len);
|
||||||
byteBuffer.position(ofs + len);
|
byteBuffer.position(ofs + len);
|
||||||
state = S_UPDATE;
|
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException("update() failed", e);
|
throw new ProviderException("update() failed", e);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -196,7 +196,7 @@ final class P11RSACipher extends CipherSpi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void implInit(int opmode, Key key) throws InvalidKeyException {
|
private void implInit(int opmode, Key key) throws InvalidKeyException {
|
||||||
cancelOperation();
|
reset(true);
|
||||||
p11Key = P11KeyFactory.convertKey(token, key, algorithm);
|
p11Key = P11KeyFactory.convertKey(token, key, algorithm);
|
||||||
boolean encrypt;
|
boolean encrypt;
|
||||||
if (opmode == Cipher.ENCRYPT_MODE) {
|
if (opmode == Cipher.ENCRYPT_MODE) {
|
||||||
@ -241,80 +241,105 @@ final class P11RSACipher extends CipherSpi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelOperation() {
|
// reset the states to the pre-initialized values
|
||||||
token.ensureValid();
|
private void reset(boolean doCancel) {
|
||||||
if (initialized == false) {
|
if (!initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initialized = false;
|
initialized = false;
|
||||||
if ((session == null) || (token.explicitCancel == false)) {
|
try {
|
||||||
return;
|
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();
|
||||||
if (session.hasObjects() == false) {
|
if (session.hasObjects() == false) {
|
||||||
session = token.killSession(session);
|
session = token.killSession(session);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
try {
|
try {
|
||||||
PKCS11 p11 = token.p11;
|
PKCS11 p11 = token.p11;
|
||||||
int inLen = maxInputSize;
|
int inLen = maxInputSize;
|
||||||
int outLen = buffer.length;
|
int outLen = buffer.length;
|
||||||
switch (mode) {
|
long sessId = session.id();
|
||||||
case MODE_ENCRYPT:
|
switch (mode) {
|
||||||
p11.C_Encrypt
|
case MODE_ENCRYPT:
|
||||||
(session.id(), buffer, 0, inLen, buffer, 0, outLen);
|
p11.C_Encrypt(sessId, buffer, 0, inLen, buffer, 0, outLen);
|
||||||
break;
|
break;
|
||||||
case MODE_DECRYPT:
|
case MODE_DECRYPT:
|
||||||
p11.C_Decrypt
|
p11.C_Decrypt(sessId, buffer, 0, inLen, buffer, 0, outLen);
|
||||||
(session.id(), buffer, 0, inLen, buffer, 0, outLen);
|
break;
|
||||||
break;
|
case MODE_SIGN:
|
||||||
case MODE_SIGN:
|
byte[] tmpBuffer = new byte[maxInputSize];
|
||||||
byte[] tmpBuffer = new byte[maxInputSize];
|
p11.C_Sign(sessId, tmpBuffer);
|
||||||
p11.C_Sign
|
break;
|
||||||
(session.id(), tmpBuffer);
|
case MODE_VERIFY:
|
||||||
break;
|
p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer,
|
||||||
case MODE_VERIFY:
|
0, outLen);
|
||||||
p11.C_VerifyRecover
|
break;
|
||||||
(session.id(), buffer, 0, inLen, buffer, 0, outLen);
|
default:
|
||||||
break;
|
throw new ProviderException("internal error");
|
||||||
default:
|
}
|
||||||
throw new ProviderException("internal error");
|
} catch (PKCS11Exception e) {
|
||||||
|
// XXX ensure this always works, ignore error
|
||||||
}
|
}
|
||||||
} catch (PKCS11Exception e) {
|
|
||||||
// XXX ensure this always works, ignore error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureInitialized() throws PKCS11Exception {
|
private void ensureInitialized() throws PKCS11Exception {
|
||||||
token.ensureValid();
|
token.ensureValid();
|
||||||
if (initialized == false) {
|
if (!initialized) {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize() throws PKCS11Exception {
|
private void initialize() throws PKCS11Exception {
|
||||||
if (session == null) {
|
if (p11Key == null) {
|
||||||
session = token.getOpSession();
|
throw new ProviderException(
|
||||||
|
"Operation cannot be performed without " +
|
||||||
|
"calling engineInit first");
|
||||||
}
|
}
|
||||||
PKCS11 p11 = token.p11;
|
long keyID = p11Key.getKeyID();
|
||||||
CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
|
try {
|
||||||
switch (mode) {
|
if (session == null) {
|
||||||
case MODE_ENCRYPT:
|
session = token.getOpSession();
|
||||||
p11.C_EncryptInit(session.id(), ckMechanism, p11Key.keyID);
|
}
|
||||||
break;
|
PKCS11 p11 = token.p11;
|
||||||
case MODE_DECRYPT:
|
CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
|
||||||
p11.C_DecryptInit(session.id(), ckMechanism, p11Key.keyID);
|
switch (mode) {
|
||||||
break;
|
case MODE_ENCRYPT:
|
||||||
case MODE_SIGN:
|
p11.C_EncryptInit(session.id(), ckMechanism, keyID);
|
||||||
p11.C_SignInit(session.id(), ckMechanism, p11Key.keyID);
|
break;
|
||||||
break;
|
case MODE_DECRYPT:
|
||||||
case MODE_VERIFY:
|
p11.C_DecryptInit(session.id(), ckMechanism, keyID);
|
||||||
p11.C_VerifyRecoverInit(session.id(), ckMechanism, p11Key.keyID);
|
break;
|
||||||
break;
|
case MODE_SIGN:
|
||||||
default:
|
p11.C_SignInit(session.id(), ckMechanism, keyID);
|
||||||
throw new AssertionError("internal error");
|
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;
|
||||||
}
|
}
|
||||||
bufOfs = 0;
|
|
||||||
initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void implUpdate(byte[] in, int inOfs, int inLen) {
|
private void implUpdate(byte[] in, int inOfs, int inLen) {
|
||||||
@ -377,8 +402,7 @@ final class P11RSACipher extends CipherSpi {
|
|||||||
throw (BadPaddingException)new BadPaddingException
|
throw (BadPaddingException)new BadPaddingException
|
||||||
("doFinal() failed").initCause(e);
|
("doFinal() failed").initCause(e);
|
||||||
} finally {
|
} finally {
|
||||||
initialized = false;
|
reset(false);
|
||||||
session = token.releaseSession(session);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,13 +476,17 @@ final class P11RSACipher extends CipherSpi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Session s = null;
|
Session s = null;
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
|
long sKeyID = sKey.getKeyID();
|
||||||
try {
|
try {
|
||||||
s = token.getOpSession();
|
s = token.getOpSession();
|
||||||
return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
|
return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
|
||||||
p11Key.keyID, sKey.keyID);
|
p11KeyID, sKeyID);
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new InvalidKeyException("wrap() failed", e);
|
throw new InvalidKeyException("wrap() failed", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
sKey.releaseKeyID();
|
||||||
token.releaseSession(s);
|
token.releaseSession(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -518,6 +546,7 @@ final class P11RSACipher extends CipherSpi {
|
|||||||
} else {
|
} else {
|
||||||
Session s = null;
|
Session s = null;
|
||||||
SecretKey secretKey = null;
|
SecretKey secretKey = null;
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
s = token.getObjSession();
|
s = token.getObjSession();
|
||||||
@ -528,9 +557,10 @@ final class P11RSACipher extends CipherSpi {
|
|||||||
};
|
};
|
||||||
attributes = token.getAttributes(
|
attributes = token.getAttributes(
|
||||||
O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
||||||
|
|
||||||
long keyID = token.p11.C_UnwrapKey(s.id(),
|
long keyID = token.p11.C_UnwrapKey(s.id(),
|
||||||
new CK_MECHANISM(mechanism), p11Key.keyID,
|
new CK_MECHANISM(mechanism), p11KeyID,
|
||||||
wrappedKey, attributes);
|
wrappedKey, attributes);
|
||||||
secretKey = P11Key.secretKey(s, keyID,
|
secretKey = P11Key.secretKey(s, keyID,
|
||||||
algorithm, 48 << 3, attributes);
|
algorithm, 48 << 3, attributes);
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
@ -554,6 +584,7 @@ final class P11RSACipher extends CipherSpi {
|
|||||||
|
|
||||||
return secretKey;
|
return secretKey;
|
||||||
} finally {
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
token.releaseSession(s);
|
token.releaseSession(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,12 @@ final class P11RSAKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_MODULUS),
|
new CK_ATTRIBUTE(CKA_MODULUS),
|
||||||
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
|
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
KeySpec spec = new RSAPublicKeySpec(
|
KeySpec spec = new RSAPublicKeySpec(
|
||||||
attributes[0].getBigInteger(),
|
attributes[0].getBigInteger(),
|
||||||
attributes[1].getBigInteger()
|
attributes[1].getBigInteger()
|
||||||
@ -289,7 +294,13 @@ final class P11RSAKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_EXPONENT_2),
|
new CK_ATTRIBUTE(CKA_EXPONENT_2),
|
||||||
new CK_ATTRIBUTE(CKA_COEFFICIENT),
|
new CK_ATTRIBUTE(CKA_COEFFICIENT),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
|
||||||
KeySpec spec = new RSAPrivateCrtKeySpec(
|
KeySpec spec = new RSAPrivateCrtKeySpec(
|
||||||
attributes[0].getBigInteger(),
|
attributes[0].getBigInteger(),
|
||||||
attributes[1].getBigInteger(),
|
attributes[1].getBigInteger(),
|
||||||
@ -307,7 +318,13 @@ final class P11RSAKeyFactory extends P11KeyFactory {
|
|||||||
new CK_ATTRIBUTE(CKA_MODULUS),
|
new CK_ATTRIBUTE(CKA_MODULUS),
|
||||||
new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
|
new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
|
||||||
};
|
};
|
||||||
token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
|
long keyID = key.getKeyID();
|
||||||
|
try {
|
||||||
|
token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
|
||||||
|
} finally {
|
||||||
|
key.releaseKeyID();
|
||||||
|
}
|
||||||
|
|
||||||
KeySpec spec = new RSAPrivateKeySpec(
|
KeySpec spec = new RSAPrivateKeySpec(
|
||||||
attributes[0].getBigInteger(),
|
attributes[0].getBigInteger(),
|
||||||
attributes[1].getBigInteger()
|
attributes[1].getBigInteger()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -146,20 +146,24 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
|
|||||||
P11Key p11Key = (P11Key)key;
|
P11Key p11Key = (P11Key)key;
|
||||||
if (p11Key.token == token) {
|
if (p11Key.token == token) {
|
||||||
if (extraAttrs != null) {
|
if (extraAttrs != null) {
|
||||||
|
P11Key newP11Key = null;
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getObjSession();
|
session = token.getObjSession();
|
||||||
long newKeyID = token.p11.C_CopyObject(session.id(),
|
long newKeyID = token.p11.C_CopyObject(session.id(),
|
||||||
p11Key.keyID, extraAttrs);
|
p11KeyID, extraAttrs);
|
||||||
p11Key = (P11Key) (P11Key.secretKey(session,
|
newP11Key = (P11Key) (P11Key.secretKey(session,
|
||||||
newKeyID, p11Key.algorithm, p11Key.keyLength,
|
newKeyID, p11Key.algorithm, p11Key.keyLength,
|
||||||
extraAttrs));
|
extraAttrs));
|
||||||
} catch (PKCS11Exception p11e) {
|
} catch (PKCS11Exception p11e) {
|
||||||
throw new InvalidKeyException
|
throw new InvalidKeyException
|
||||||
("Cannot duplicate the PKCS11 key", p11e);
|
("Cannot duplicate the PKCS11 key", p11e);
|
||||||
} finally {
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
|
p11Key = newP11Key;
|
||||||
}
|
}
|
||||||
return p11Key;
|
return p11Key;
|
||||||
}
|
}
|
||||||
|
@ -263,27 +263,33 @@ final class P11Signature extends SignatureSpi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureInitialized() {
|
// reset the states to the pre-initialized values
|
||||||
token.ensureValid();
|
private void reset(boolean doCancel) {
|
||||||
if (initialized == false) {
|
|
||||||
initialize();
|
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() {
|
private void cancelOperation() {
|
||||||
|
|
||||||
token.ensureValid();
|
token.ensureValid();
|
||||||
if (initialized == false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
initialized = false;
|
|
||||||
if ((session == null) || (token.explicitCancel == false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (session.hasObjects() == false) {
|
if (session.hasObjects() == false) {
|
||||||
session = token.killSession(session);
|
session = token.killSession(session);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
try {
|
|
||||||
// "cancel" operation by finishing it
|
// "cancel" operation by finishing it
|
||||||
// XXX make sure all this always works correctly
|
// XXX make sure all this always works correctly
|
||||||
if (mode == M_SIGN) {
|
if (mode == M_SIGN) {
|
||||||
@ -303,8 +309,8 @@ final class P11Signature extends SignatureSpi {
|
|||||||
throw new ProviderException("cancel failed", e);
|
throw new ProviderException("cancel failed", e);
|
||||||
}
|
}
|
||||||
} else { // M_VERIFY
|
} else { // M_VERIFY
|
||||||
|
byte[] signature;
|
||||||
try {
|
try {
|
||||||
byte[] signature;
|
|
||||||
if (keyAlgorithm.equals("DSA")) {
|
if (keyAlgorithm.equals("DSA")) {
|
||||||
signature = new byte[40];
|
signature = new byte[40];
|
||||||
} else {
|
} else {
|
||||||
@ -322,31 +328,48 @@ final class P11Signature extends SignatureSpi {
|
|||||||
token.p11.C_Verify(session.id(), digest, signature);
|
token.p11.C_Verify(session.id(), digest, signature);
|
||||||
}
|
}
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
// will fail since the signature is incorrect
|
long errorCode = e.getErrorCode();
|
||||||
// XXX check error code
|
if ((errorCode == CKR_SIGNATURE_INVALID) ||
|
||||||
|
(errorCode == CKR_SIGNATURE_LEN_RANGE)) {
|
||||||
|
// expected since signature is incorrect
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new ProviderException("cancel failed", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
}
|
||||||
session = token.releaseSession(session);
|
}
|
||||||
|
|
||||||
|
private void ensureInitialized() {
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// assumes current state is initialized == false
|
// assumes current state is initialized == false
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
|
|
||||||
|
if (p11Key == null) {
|
||||||
|
throw new ProviderException(
|
||||||
|
"Operation cannot be performed without " +
|
||||||
|
"calling engineInit first");
|
||||||
|
}
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
try {
|
try {
|
||||||
|
token.ensureValid();
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
session = token.getOpSession();
|
session = token.getOpSession();
|
||||||
}
|
}
|
||||||
if (mode == M_SIGN) {
|
if (mode == M_SIGN) {
|
||||||
token.p11.C_SignInit(session.id(),
|
token.p11.C_SignInit(session.id(),
|
||||||
new CK_MECHANISM(mechanism), p11Key.keyID);
|
new CK_MECHANISM(mechanism), keyID);
|
||||||
} else {
|
} else {
|
||||||
token.p11.C_VerifyInit(session.id(),
|
token.p11.C_VerifyInit(session.id(),
|
||||||
new CK_MECHANISM(mechanism), p11Key.keyID);
|
new CK_MECHANISM(mechanism), keyID);
|
||||||
}
|
}
|
||||||
initialized = true;
|
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
// release session when initialization failed
|
p11Key.releaseKeyID();
|
||||||
session = token.releaseSession(session);
|
session = token.releaseSession(session);
|
||||||
throw new ProviderException("Initialization failed", e);
|
throw new ProviderException("Initialization failed", e);
|
||||||
}
|
}
|
||||||
@ -356,6 +379,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
md.reset();
|
md.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkKeySize(String keyAlgo, Key key)
|
private void checkKeySize(String keyAlgo, Key key)
|
||||||
@ -444,6 +468,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
@Override
|
@Override
|
||||||
protected void engineInitVerify(PublicKey publicKey)
|
protected void engineInitVerify(PublicKey publicKey)
|
||||||
throws InvalidKeyException {
|
throws InvalidKeyException {
|
||||||
|
|
||||||
if (publicKey == null) {
|
if (publicKey == null) {
|
||||||
throw new InvalidKeyException("Key must not be null");
|
throw new InvalidKeyException("Key must not be null");
|
||||||
}
|
}
|
||||||
@ -451,7 +476,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
if (publicKey != p11Key) {
|
if (publicKey != p11Key) {
|
||||||
checkKeySize(keyAlgorithm, publicKey);
|
checkKeySize(keyAlgorithm, publicKey);
|
||||||
}
|
}
|
||||||
cancelOperation();
|
reset(true);
|
||||||
mode = M_VERIFY;
|
mode = M_VERIFY;
|
||||||
p11Key = P11KeyFactory.convertKey(token, publicKey, keyAlgorithm);
|
p11Key = P11KeyFactory.convertKey(token, publicKey, keyAlgorithm);
|
||||||
initialize();
|
initialize();
|
||||||
@ -461,6 +486,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
@Override
|
@Override
|
||||||
protected void engineInitSign(PrivateKey privateKey)
|
protected void engineInitSign(PrivateKey privateKey)
|
||||||
throws InvalidKeyException {
|
throws InvalidKeyException {
|
||||||
|
|
||||||
if (privateKey == null) {
|
if (privateKey == null) {
|
||||||
throw new InvalidKeyException("Key must not be null");
|
throw new InvalidKeyException("Key must not be null");
|
||||||
}
|
}
|
||||||
@ -468,7 +494,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
if (privateKey != p11Key) {
|
if (privateKey != p11Key) {
|
||||||
checkKeySize(keyAlgorithm, privateKey);
|
checkKeySize(keyAlgorithm, privateKey);
|
||||||
}
|
}
|
||||||
cancelOperation();
|
reset(true);
|
||||||
mode = M_SIGN;
|
mode = M_SIGN;
|
||||||
p11Key = P11KeyFactory.convertKey(token, privateKey, keyAlgorithm);
|
p11Key = P11KeyFactory.convertKey(token, privateKey, keyAlgorithm);
|
||||||
initialize();
|
initialize();
|
||||||
@ -503,6 +529,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
@Override
|
@Override
|
||||||
protected void engineUpdate(byte[] b, int ofs, int len)
|
protected void engineUpdate(byte[] b, int ofs, int len)
|
||||||
throws SignatureException {
|
throws SignatureException {
|
||||||
|
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return;
|
return;
|
||||||
@ -521,8 +548,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
}
|
}
|
||||||
bytesProcessed += len;
|
bytesProcessed += len;
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
initialized = false;
|
reset(false);
|
||||||
session = token.releaseSession(session);
|
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -546,6 +572,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
// see JCA spec
|
// see JCA spec
|
||||||
@Override
|
@Override
|
||||||
protected void engineUpdate(ByteBuffer byteBuffer) {
|
protected void engineUpdate(ByteBuffer byteBuffer) {
|
||||||
|
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
int len = byteBuffer.remaining();
|
int len = byteBuffer.remaining();
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
@ -571,8 +598,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
bytesProcessed += len;
|
bytesProcessed += len;
|
||||||
byteBuffer.position(ofs + len);
|
byteBuffer.position(ofs + len);
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
initialized = false;
|
reset(false);
|
||||||
session = token.releaseSession(session);
|
|
||||||
throw new ProviderException("Update failed", e);
|
throw new ProviderException("Update failed", e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -589,6 +615,7 @@ final class P11Signature extends SignatureSpi {
|
|||||||
bytesProcessed += len;
|
bytesProcessed += len;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
reset(false);
|
||||||
throw new ProviderException("Internal error");
|
throw new ProviderException("Internal error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,7 +623,9 @@ final class P11Signature extends SignatureSpi {
|
|||||||
// see JCA spec
|
// see JCA spec
|
||||||
@Override
|
@Override
|
||||||
protected byte[] engineSign() throws SignatureException {
|
protected byte[] engineSign() throws SignatureException {
|
||||||
|
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
|
boolean doCancel = true;
|
||||||
try {
|
try {
|
||||||
byte[] signature;
|
byte[] signature;
|
||||||
if (type == T_UPDATE) {
|
if (type == T_UPDATE) {
|
||||||
@ -633,6 +662,8 @@ final class P11Signature extends SignatureSpi {
|
|||||||
signature = token.p11.C_Sign(session.id(), data);
|
signature = token.p11.C_Sign(session.id(), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
doCancel = false;
|
||||||
|
|
||||||
if (keyAlgorithm.equals("RSA")) {
|
if (keyAlgorithm.equals("RSA")) {
|
||||||
return signature;
|
return signature;
|
||||||
} else {
|
} else {
|
||||||
@ -643,20 +674,21 @@ final class P11Signature extends SignatureSpi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (PKCS11Exception pe) {
|
} catch (PKCS11Exception pe) {
|
||||||
|
doCancel = false;
|
||||||
throw new ProviderException(pe);
|
throw new ProviderException(pe);
|
||||||
} catch (SignatureException | ProviderException e) {
|
} catch (SignatureException | ProviderException e) {
|
||||||
cancelOperation();
|
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
initialized = false;
|
reset(doCancel);
|
||||||
session = token.releaseSession(session);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCA spec
|
// see JCA spec
|
||||||
@Override
|
@Override
|
||||||
protected boolean engineVerify(byte[] signature) throws SignatureException {
|
protected boolean engineVerify(byte[] signature) throws SignatureException {
|
||||||
|
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
|
boolean doCancel = true;
|
||||||
try {
|
try {
|
||||||
if (!p1363Format) {
|
if (!p1363Format) {
|
||||||
if (keyAlgorithm.equals("DSA")) {
|
if (keyAlgorithm.equals("DSA")) {
|
||||||
@ -698,8 +730,10 @@ final class P11Signature extends SignatureSpi {
|
|||||||
token.p11.C_Verify(session.id(), data, signature);
|
token.p11.C_Verify(session.id(), data, signature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
doCancel = false;
|
||||||
return true;
|
return true;
|
||||||
} catch (PKCS11Exception pe) {
|
} catch (PKCS11Exception pe) {
|
||||||
|
doCancel = false;
|
||||||
long errorCode = pe.getErrorCode();
|
long errorCode = pe.getErrorCode();
|
||||||
if (errorCode == CKR_SIGNATURE_INVALID) {
|
if (errorCode == CKR_SIGNATURE_INVALID) {
|
||||||
return false;
|
return false;
|
||||||
@ -714,11 +748,9 @@ final class P11Signature extends SignatureSpi {
|
|||||||
}
|
}
|
||||||
throw new ProviderException(pe);
|
throw new ProviderException(pe);
|
||||||
} catch (SignatureException | ProviderException e) {
|
} catch (SignatureException | ProviderException e) {
|
||||||
cancelOperation();
|
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
initialized = false;
|
reset(doCancel);
|
||||||
session = token.releaseSession(session);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +189,13 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
|
|||||||
attributes = token.getAttributes
|
attributes = token.getAttributes
|
||||||
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
|
||||||
// the returned keyID is a dummy, ignore
|
// the returned keyID is a dummy, ignore
|
||||||
token.p11.C_DeriveKey(session.id(),
|
long p11KeyID = p11Key.getKeyID();
|
||||||
ckMechanism, p11Key.keyID, attributes);
|
try {
|
||||||
|
token.p11.C_DeriveKey(session.id(),
|
||||||
|
ckMechanism, p11KeyID, attributes);
|
||||||
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
|
}
|
||||||
|
|
||||||
CK_SSL3_KEY_MAT_OUT out = null;
|
CK_SSL3_KEY_MAT_OUT out = null;
|
||||||
if (params instanceof CK_SSL3_KEY_MAT_PARAMS) {
|
if (params instanceof CK_SSL3_KEY_MAT_PARAMS) {
|
||||||
|
@ -160,12 +160,13 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
|
|||||||
ckMechanism = new CK_MECHANISM(mechanism, params);
|
ckMechanism = new CK_MECHANISM(mechanism, params);
|
||||||
}
|
}
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long p11KeyID = p11Key.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getObjSession();
|
session = token.getObjSession();
|
||||||
CK_ATTRIBUTE[] attributes = token.getAttributes(O_GENERATE,
|
CK_ATTRIBUTE[] attributes = token.getAttributes(O_GENERATE,
|
||||||
CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
|
CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
|
||||||
long keyID = token.p11.C_DeriveKey(session.id(),
|
long keyID = token.p11.C_DeriveKey(session.id(),
|
||||||
ckMechanism, p11Key.keyID, attributes);
|
ckMechanism, p11KeyID, attributes);
|
||||||
int major, minor;
|
int major, minor;
|
||||||
if (ckVersion == null) {
|
if (ckVersion == null) {
|
||||||
major = -1;
|
major = -1;
|
||||||
@ -174,12 +175,12 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
|
|||||||
major = ckVersion.major;
|
major = ckVersion.major;
|
||||||
minor = ckVersion.minor;
|
minor = ckVersion.minor;
|
||||||
}
|
}
|
||||||
SecretKey key = P11Key.masterSecretKey(session, keyID,
|
return P11Key.masterSecretKey(session, keyID,
|
||||||
"TlsMasterSecret", 48 << 3, attributes, major, minor);
|
"TlsMasterSecret", 48 << 3, attributes, major, minor);
|
||||||
return key;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ProviderException("Could not generate key", e);
|
throw new ProviderException("Could not generate key", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,34 +146,36 @@ final class P11TlsPrfGenerator extends KeyGeneratorSpi {
|
|||||||
Functions.getHashMechId(spec.getPRFHashAlg()),
|
Functions.getHashMechId(spec.getPRFHashAlg()),
|
||||||
spec.getOutputLength(), ulServerOrClient);
|
spec.getOutputLength(), ulServerOrClient);
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getOpSession();
|
session = token.getOpSession();
|
||||||
token.p11.C_SignInit(session.id(),
|
token.p11.C_SignInit(session.id(),
|
||||||
new CK_MECHANISM(mechanism, params), p11Key.keyID);
|
new CK_MECHANISM(mechanism, params), keyID);
|
||||||
token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
|
token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
|
||||||
byte[] out = token.p11.C_SignFinal
|
byte[] out = token.p11.C_SignFinal
|
||||||
(session.id(), spec.getOutputLength());
|
(session.id(), spec.getOutputLength());
|
||||||
k = new SecretKeySpec(out, "TlsPrf");
|
return new SecretKeySpec(out, "TlsPrf");
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException("Could not calculate PRF", e);
|
throw new ProviderException("Could not calculate PRF", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new ProviderException("Only Finished message authentication code"+
|
throw new ProviderException("Only Finished message authentication code"+
|
||||||
" generation supported for TLS 1.2.");
|
" generation supported for TLS 1.2.");
|
||||||
}
|
}
|
||||||
return k;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] label = P11Util.getBytesUTF8(spec.getLabel());
|
byte[] label = P11Util.getBytesUTF8(spec.getLabel());
|
||||||
|
|
||||||
if (mechanism == CKM_NSS_TLS_PRF_GENERAL) {
|
if (mechanism == CKM_NSS_TLS_PRF_GENERAL) {
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getOpSession();
|
session = token.getOpSession();
|
||||||
token.p11.C_SignInit
|
token.p11.C_SignInit
|
||||||
(session.id(), new CK_MECHANISM(mechanism), p11Key.keyID);
|
(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, label, 0, label.length);
|
||||||
token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
|
token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
|
||||||
byte[] out = token.p11.C_SignFinal
|
byte[] out = token.p11.C_SignFinal
|
||||||
@ -182,6 +184,7 @@ final class P11TlsPrfGenerator extends KeyGeneratorSpi {
|
|||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException("Could not calculate PRF", e);
|
throw new ProviderException("Could not calculate PRF", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,15 +195,16 @@ final class P11TlsPrfGenerator extends KeyGeneratorSpi {
|
|||||||
CK_TLS_PRF_PARAMS params = new CK_TLS_PRF_PARAMS(seed, label, out);
|
CK_TLS_PRF_PARAMS params = new CK_TLS_PRF_PARAMS(seed, label, out);
|
||||||
|
|
||||||
Session session = null;
|
Session session = null;
|
||||||
|
long keyID = p11Key.getKeyID();
|
||||||
try {
|
try {
|
||||||
session = token.getOpSession();
|
session = token.getOpSession();
|
||||||
long keyID = token.p11.C_DeriveKey(session.id(),
|
token.p11.C_DeriveKey(session.id(),
|
||||||
new CK_MECHANISM(mechanism, params), p11Key.keyID, null);
|
new CK_MECHANISM(mechanism, params), keyID, null);
|
||||||
// ignore keyID, returned PRF bytes are in 'out'
|
|
||||||
return new SecretKeySpec(out, "TlsPrf");
|
return new SecretKeySpec(out, "TlsPrf");
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new ProviderException("Could not calculate PRF", e);
|
throw new ProviderException("Could not calculate PRF", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
p11Key.releaseKeyID();
|
||||||
token.releaseSession(session);
|
token.releaseSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
|
||||||
@ -1290,6 +1290,46 @@ public class PKCS11 {
|
|||||||
* Key management
|
* Key management
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getNativeKeyInfo gets the key object attributes and values as an opaque
|
||||||
|
* byte array to be used in createNativeKey method.
|
||||||
|
* (Key management)
|
||||||
|
*
|
||||||
|
* @param hSession the session's handle
|
||||||
|
* @param hKey key's handle
|
||||||
|
* @param hWrappingKey key handle for wrapping the extracted sensitive keys.
|
||||||
|
* -1 if not used.
|
||||||
|
* @param pWrappingMech mechanism for wrapping the extracted sensitive keys
|
||||||
|
* @return an opaque byte array containing the key object attributes
|
||||||
|
* and values
|
||||||
|
* @exception PKCS11Exception If an internal PKCS#11 function returns other
|
||||||
|
* value than CKR_OK.
|
||||||
|
* @preconditions
|
||||||
|
* @postconditions
|
||||||
|
*/
|
||||||
|
public native byte[] getNativeKeyInfo(long hSession, long hKey,
|
||||||
|
long hWrappingKey, CK_MECHANISM pWrappingMech) throws PKCS11Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* createNativeKey creates a key object with attributes and values
|
||||||
|
* specified by parameter as an opaque byte array.
|
||||||
|
* (Key management)
|
||||||
|
*
|
||||||
|
* @param hSession the session's handle
|
||||||
|
* @param keyInfo opaque byte array containing key object attributes
|
||||||
|
* and values
|
||||||
|
* @param hWrappingKey key handle for unwrapping the extracted sensitive keys.
|
||||||
|
* -1 if not used.
|
||||||
|
* @param pWrappingMech mechanism for unwrapping the extracted sensitive keys
|
||||||
|
* @return key object handle
|
||||||
|
* @exception PKCS11Exception If an internal PKCS#11 function returns other
|
||||||
|
* value than CKR_OK.
|
||||||
|
* @preconditions
|
||||||
|
* @postconditions
|
||||||
|
*/
|
||||||
|
public native long createNativeKey(long hSession, byte[] keyInfo,
|
||||||
|
long hWrappingKey, CK_MECHANISM pWrappingMech) throws PKCS11Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* C_GenerateKey generates a secret key, creating a new key
|
* C_GenerateKey generates a secret key, creating a new key
|
||||||
* object.
|
* object.
|
||||||
|
@ -54,6 +54,444 @@
|
|||||||
|
|
||||||
#include "sun_security_pkcs11_wrapper_PKCS11.h"
|
#include "sun_security_pkcs11_wrapper_PKCS11.h"
|
||||||
|
|
||||||
|
#ifdef P11_ENABLE_GETNATIVEKEYINFO
|
||||||
|
|
||||||
|
#define CK_ATTRIBUTES_TEMPLATE_LENGTH (CK_ULONG)61U
|
||||||
|
|
||||||
|
static CK_ATTRIBUTE ckpAttributesTemplate[CK_ATTRIBUTES_TEMPLATE_LENGTH] = {
|
||||||
|
{CKA_CLASS, 0, 0},
|
||||||
|
{CKA_TOKEN, 0, 0},
|
||||||
|
{CKA_PRIVATE, 0, 0},
|
||||||
|
{CKA_LABEL, 0, 0},
|
||||||
|
{CKA_APPLICATION, 0, 0},
|
||||||
|
{CKA_VALUE, 0, 0},
|
||||||
|
{CKA_OBJECT_ID, 0, 0},
|
||||||
|
{CKA_CERTIFICATE_TYPE, 0, 0},
|
||||||
|
{CKA_ISSUER, 0, 0},
|
||||||
|
{CKA_SERIAL_NUMBER, 0, 0},
|
||||||
|
{CKA_AC_ISSUER, 0, 0},
|
||||||
|
{CKA_OWNER, 0, 0},
|
||||||
|
{CKA_ATTR_TYPES, 0, 0},
|
||||||
|
{CKA_TRUSTED, 0, 0},
|
||||||
|
{CKA_KEY_TYPE, 0, 0},
|
||||||
|
{CKA_SUBJECT, 0, 0},
|
||||||
|
{CKA_ID, 0, 0},
|
||||||
|
{CKA_SENSITIVE, 0, 0},
|
||||||
|
{CKA_ENCRYPT, 0, 0},
|
||||||
|
{CKA_DECRYPT, 0, 0},
|
||||||
|
{CKA_WRAP, 0, 0},
|
||||||
|
{CKA_UNWRAP, 0, 0},
|
||||||
|
{CKA_SIGN, 0, 0},
|
||||||
|
{CKA_SIGN_RECOVER, 0, 0},
|
||||||
|
{CKA_VERIFY, 0, 0},
|
||||||
|
{CKA_VERIFY_RECOVER, 0, 0},
|
||||||
|
{CKA_DERIVE, 0, 0},
|
||||||
|
{CKA_START_DATE, 0, 0},
|
||||||
|
{CKA_END_DATE, 0, 0},
|
||||||
|
{CKA_MODULUS, 0, 0},
|
||||||
|
{CKA_MODULUS_BITS, 0, 0},
|
||||||
|
{CKA_PUBLIC_EXPONENT, 0, 0},
|
||||||
|
{CKA_PRIVATE_EXPONENT, 0, 0},
|
||||||
|
{CKA_PRIME_1, 0, 0},
|
||||||
|
{CKA_PRIME_2, 0, 0},
|
||||||
|
{CKA_EXPONENT_1, 0, 0},
|
||||||
|
{CKA_EXPONENT_2, 0, 0},
|
||||||
|
{CKA_COEFFICIENT, 0, 0},
|
||||||
|
{CKA_PRIME, 0, 0},
|
||||||
|
{CKA_SUBPRIME, 0, 0},
|
||||||
|
{CKA_BASE, 0, 0},
|
||||||
|
{CKA_PRIME_BITS, 0, 0},
|
||||||
|
{CKA_SUB_PRIME_BITS, 0, 0},
|
||||||
|
{CKA_VALUE_BITS, 0, 0},
|
||||||
|
{CKA_VALUE_LEN, 0, 0},
|
||||||
|
{CKA_EXTRACTABLE, 0, 0},
|
||||||
|
{CKA_LOCAL, 0, 0},
|
||||||
|
{CKA_NEVER_EXTRACTABLE, 0, 0},
|
||||||
|
{CKA_ALWAYS_SENSITIVE, 0, 0},
|
||||||
|
{CKA_KEY_GEN_MECHANISM, 0, 0},
|
||||||
|
{CKA_MODIFIABLE, 0, 0},
|
||||||
|
{CKA_ECDSA_PARAMS, 0, 0},
|
||||||
|
{CKA_EC_PARAMS, 0, 0},
|
||||||
|
{CKA_EC_POINT, 0, 0},
|
||||||
|
{CKA_SECONDARY_AUTH, 0, 0},
|
||||||
|
{CKA_AUTH_PIN_FLAGS, 0, 0},
|
||||||
|
{CKA_HW_FEATURE_TYPE, 0, 0},
|
||||||
|
{CKA_RESET_ON_INIT, 0, 0},
|
||||||
|
{CKA_HAS_RESET, 0, 0},
|
||||||
|
{CKA_VENDOR_DEFINED, 0, 0},
|
||||||
|
{CKA_NETSCAPE_DB, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: sun_security_pkcs11_wrapper_PKCS11
|
||||||
|
* Method: getNativeKeyInfo
|
||||||
|
* Signature: (JJJLsun/security/pkcs11/wrapper/CK_MECHANISM;)[B
|
||||||
|
* Parametermapping: *PKCS11*
|
||||||
|
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
|
||||||
|
* @param jlong jKeyHandle CK_OBJECT_HANDLE hObject
|
||||||
|
* @param jlong jWrappingKeyHandle CK_OBJECT_HANDLE hObject
|
||||||
|
* @param jobject jWrappingMech CK_MECHANISM_PTR pMechanism
|
||||||
|
* @return jbyteArray jNativeKeyInfo -
|
||||||
|
*/
|
||||||
|
JNIEXPORT jbyteArray JNICALL
|
||||||
|
Java_sun_security_pkcs11_wrapper_PKCS11_getNativeKeyInfo
|
||||||
|
(JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jKeyHandle,
|
||||||
|
jlong jWrappingKeyHandle, jobject jWrappingMech)
|
||||||
|
{
|
||||||
|
jbyteArray returnValue = NULL;
|
||||||
|
CK_SESSION_HANDLE ckSessionHandle = jLongToCKULong(jSessionHandle);
|
||||||
|
CK_OBJECT_HANDLE ckObjectHandle = jLongToCKULong(jKeyHandle);
|
||||||
|
CK_ATTRIBUTE_PTR ckpAttributes = NULL;
|
||||||
|
CK_RV rv;
|
||||||
|
jbyteArray nativeKeyInfoArray = NULL;
|
||||||
|
jbyteArray nativeKeyInfoWrappedKeyArray = NULL;
|
||||||
|
jbyte* nativeKeyInfoArrayRaw = NULL;
|
||||||
|
jbyte* nativeKeyInfoWrappedKeyArrayRaw = NULL;
|
||||||
|
unsigned int sensitiveAttributePosition = (unsigned int)-1;
|
||||||
|
unsigned int i = 0U;
|
||||||
|
unsigned long totalDataSize = 0UL, attributesCount = 0UL;
|
||||||
|
unsigned long totalCkAttributesSize = 0UL, totalNativeKeyInfoArraySize = 0UL;
|
||||||
|
unsigned long* wrappedKeySizePtr = NULL;
|
||||||
|
jbyte* nativeKeyInfoArrayRawCkAttributes = NULL;
|
||||||
|
jbyte* nativeKeyInfoArrayRawCkAttributesPtr = NULL;
|
||||||
|
jbyte* nativeKeyInfoArrayRawDataPtr = NULL;
|
||||||
|
CK_MECHANISM ckMechanism;
|
||||||
|
char iv[16] = {0x0};
|
||||||
|
CK_ULONG ckWrappedKeyLength = 0U;
|
||||||
|
unsigned long* wrappedKeySizeWrappedKeyArrayPtr = NULL;
|
||||||
|
CK_BYTE_PTR wrappedKeyBufferPtr = NULL;
|
||||||
|
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
|
||||||
|
CK_OBJECT_CLASS class;
|
||||||
|
CK_KEY_TYPE keyType;
|
||||||
|
CK_BBOOL sensitive;
|
||||||
|
CK_BBOOL netscapeAttributeValueNeeded = CK_FALSE;
|
||||||
|
CK_ATTRIBUTE ckNetscapeAttributesTemplate[4];
|
||||||
|
ckNetscapeAttributesTemplate[0].type = CKA_CLASS;
|
||||||
|
ckNetscapeAttributesTemplate[1].type = CKA_KEY_TYPE;
|
||||||
|
ckNetscapeAttributesTemplate[2].type = CKA_SENSITIVE;
|
||||||
|
ckNetscapeAttributesTemplate[3].type = CKA_NETSCAPE_DB;
|
||||||
|
ckNetscapeAttributesTemplate[0].pValue = &class;
|
||||||
|
ckNetscapeAttributesTemplate[1].pValue = &keyType;
|
||||||
|
ckNetscapeAttributesTemplate[2].pValue = &sensitive;
|
||||||
|
ckNetscapeAttributesTemplate[3].pValue = 0;
|
||||||
|
ckNetscapeAttributesTemplate[0].ulValueLen = sizeof(class);
|
||||||
|
ckNetscapeAttributesTemplate[1].ulValueLen = sizeof(keyType);
|
||||||
|
ckNetscapeAttributesTemplate[2].ulValueLen = sizeof(sensitive);
|
||||||
|
ckNetscapeAttributesTemplate[3].ulValueLen = 0;
|
||||||
|
|
||||||
|
if (ckpFunctions == NULL) { goto cleanup; }
|
||||||
|
|
||||||
|
// If key is private and of DSA or EC type, NSS may require CKA_NETSCAPE_DB
|
||||||
|
// attribute to unwrap it.
|
||||||
|
rv = (*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
|
||||||
|
ckNetscapeAttributesTemplate,
|
||||||
|
sizeof(ckNetscapeAttributesTemplate)/sizeof(CK_ATTRIBUTE));
|
||||||
|
|
||||||
|
if (rv == CKR_OK && class == CKO_PRIVATE_KEY &&
|
||||||
|
(keyType == CKK_EC || keyType == CKK_DSA) &&
|
||||||
|
sensitive == CK_TRUE &&
|
||||||
|
ckNetscapeAttributesTemplate[3].ulValueLen == CK_UNAVAILABLE_INFORMATION) {
|
||||||
|
// We cannot set the attribute through C_SetAttributeValue here
|
||||||
|
// because it might be read-only. However, we can add it to
|
||||||
|
// the extracted buffer.
|
||||||
|
netscapeAttributeValueNeeded = CK_TRUE;
|
||||||
|
TRACE0("DEBUG: override CKA_NETSCAPE_DB attr value to TRUE\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ckpAttributes = (CK_ATTRIBUTE_PTR)malloc(
|
||||||
|
CK_ATTRIBUTES_TEMPLATE_LENGTH * sizeof(CK_ATTRIBUTE));
|
||||||
|
if (ckpAttributes == NULL) {
|
||||||
|
throwOutOfMemoryError(env, 0);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(ckpAttributes, ckpAttributesTemplate,
|
||||||
|
CK_ATTRIBUTES_TEMPLATE_LENGTH * sizeof(CK_ATTRIBUTE));
|
||||||
|
|
||||||
|
// Get sizes for value buffers
|
||||||
|
// NOTE: may return an error code but length values are filled anyways
|
||||||
|
(*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
|
||||||
|
ckpAttributes, CK_ATTRIBUTES_TEMPLATE_LENGTH);
|
||||||
|
|
||||||
|
for (i = 0; i < CK_ATTRIBUTES_TEMPLATE_LENGTH; i++) {
|
||||||
|
if ((ckpAttributes+i)->ulValueLen != CK_UNAVAILABLE_INFORMATION) {
|
||||||
|
totalDataSize += (ckpAttributes+i)->ulValueLen;
|
||||||
|
if ((ckpAttributes+i)->type == CKA_SENSITIVE) {
|
||||||
|
sensitiveAttributePosition = attributesCount;
|
||||||
|
TRACE0("DEBUG: GetNativeKeyInfo key is sensitive");
|
||||||
|
}
|
||||||
|
attributesCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netscapeAttributeValueNeeded) {
|
||||||
|
attributesCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a single buffer to hold valid attributes and attribute's values
|
||||||
|
// Buffer structure: [ attributes-size, [ ... attributes ... ],
|
||||||
|
// values-size, [ ... values ... ], wrapped-key-size,
|
||||||
|
// [ ... wrapped-key ... ] ]
|
||||||
|
// * sizes are expressed in bytes and data type is unsigned long
|
||||||
|
totalCkAttributesSize = attributesCount * sizeof(CK_ATTRIBUTE);
|
||||||
|
TRACE1("DEBUG: GetNativeKeyInfo attributesCount = %lu\n", attributesCount);
|
||||||
|
TRACE1("DEBUG: GetNativeKeyInfo sizeof CK_ATTRIBUTE = %lu\n", sizeof(CK_ATTRIBUTE));
|
||||||
|
TRACE1("DEBUG: GetNativeKeyInfo totalCkAttributesSize = %lu\n", totalCkAttributesSize);
|
||||||
|
TRACE1("DEBUG: GetNativeKeyInfo totalDataSize = %lu\n", totalDataSize);
|
||||||
|
|
||||||
|
totalNativeKeyInfoArraySize =
|
||||||
|
totalCkAttributesSize + sizeof(unsigned long) * 3 + totalDataSize;
|
||||||
|
|
||||||
|
TRACE1("DEBUG: GetNativeKeyInfo totalNativeKeyInfoArraySize = %lu\n", totalNativeKeyInfoArraySize);
|
||||||
|
|
||||||
|
nativeKeyInfoArray = (*env)->NewByteArray(env, totalNativeKeyInfoArraySize);
|
||||||
|
if (nativeKeyInfoArray == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeKeyInfoArrayRaw = (*env)->GetByteArrayElements(env, nativeKeyInfoArray,
|
||||||
|
NULL);
|
||||||
|
if (nativeKeyInfoArrayRaw == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrappedKeySizePtr = (unsigned long*)(nativeKeyInfoArrayRaw +
|
||||||
|
sizeof(unsigned long)*2 + totalCkAttributesSize + totalDataSize);
|
||||||
|
memcpy(nativeKeyInfoArrayRaw, &totalCkAttributesSize, sizeof(unsigned long));
|
||||||
|
|
||||||
|
memcpy(nativeKeyInfoArrayRaw + sizeof(unsigned long) + totalCkAttributesSize,
|
||||||
|
&totalDataSize, sizeof(unsigned long));
|
||||||
|
|
||||||
|
memset(wrappedKeySizePtr, 0, sizeof(unsigned long));
|
||||||
|
|
||||||
|
nativeKeyInfoArrayRawCkAttributes = nativeKeyInfoArrayRaw +
|
||||||
|
sizeof(unsigned long);
|
||||||
|
nativeKeyInfoArrayRawCkAttributesPtr = nativeKeyInfoArrayRawCkAttributes;
|
||||||
|
nativeKeyInfoArrayRawDataPtr = nativeKeyInfoArrayRaw +
|
||||||
|
totalCkAttributesSize + sizeof(unsigned long) * 2;
|
||||||
|
|
||||||
|
for (i = 0; i < CK_ATTRIBUTES_TEMPLATE_LENGTH; i++) {
|
||||||
|
if ((ckpAttributes+i)->ulValueLen != CK_UNAVAILABLE_INFORMATION) {
|
||||||
|
(*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).type =
|
||||||
|
(ckpAttributes+i)->type;
|
||||||
|
(*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen =
|
||||||
|
(ckpAttributes+i)->ulValueLen;
|
||||||
|
if ((ckpAttributes+i)->ulValueLen != 0) {
|
||||||
|
(*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue =
|
||||||
|
nativeKeyInfoArrayRawDataPtr;
|
||||||
|
} else {
|
||||||
|
(*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue = 0;
|
||||||
|
}
|
||||||
|
nativeKeyInfoArrayRawDataPtr +=
|
||||||
|
(*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen;
|
||||||
|
nativeKeyInfoArrayRawCkAttributesPtr += sizeof(CK_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE0("DEBUG: GetNativeKeyInfo finished prepping nativeKeyInfoArray\n");
|
||||||
|
|
||||||
|
// Get attribute's values
|
||||||
|
rv = (*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
|
||||||
|
(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
|
||||||
|
attributesCount);
|
||||||
|
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE0("DEBUG: GetNativeKeyInfo 1st C_GetAttributeValue call passed\n");
|
||||||
|
|
||||||
|
if (netscapeAttributeValueNeeded) {
|
||||||
|
(*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).type = CKA_NETSCAPE_DB;
|
||||||
|
// Value is not needed, public key is not used
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sensitiveAttributePosition != (unsigned int)-1) &&
|
||||||
|
*(CK_BBOOL*)(((CK_ATTRIBUTE_PTR)(((CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes)
|
||||||
|
+sensitiveAttributePosition))->pValue) == CK_TRUE) {
|
||||||
|
// Key is sensitive. Need to extract it wrapped.
|
||||||
|
if (jWrappingKeyHandle != -1) {
|
||||||
|
|
||||||
|
jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism);
|
||||||
|
rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism,
|
||||||
|
jLongToCKULong(jWrappingKeyHandle), ckObjectHandle,
|
||||||
|
NULL_PTR, &ckWrappedKeyLength);
|
||||||
|
if (ckWrappedKeyLength != 0) {
|
||||||
|
// Allocate space for getting the wrapped key
|
||||||
|
nativeKeyInfoWrappedKeyArray = (*env)->NewByteArray(env,
|
||||||
|
totalNativeKeyInfoArraySize + ckWrappedKeyLength);
|
||||||
|
if (nativeKeyInfoWrappedKeyArray == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
nativeKeyInfoWrappedKeyArrayRaw =
|
||||||
|
(*env)->GetByteArrayElements(env,
|
||||||
|
nativeKeyInfoWrappedKeyArray, NULL);
|
||||||
|
if (nativeKeyInfoWrappedKeyArrayRaw == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(nativeKeyInfoWrappedKeyArrayRaw, nativeKeyInfoArrayRaw,
|
||||||
|
totalNativeKeyInfoArraySize);
|
||||||
|
wrappedKeySizeWrappedKeyArrayPtr =
|
||||||
|
(unsigned long*)(nativeKeyInfoWrappedKeyArrayRaw +
|
||||||
|
sizeof(unsigned long)*2 + totalCkAttributesSize +
|
||||||
|
totalDataSize);
|
||||||
|
memcpy(wrappedKeySizeWrappedKeyArrayPtr, &ckWrappedKeyLength, sizeof(unsigned long));
|
||||||
|
TRACE1("DEBUG: GetNativeKeyInfo 1st C_WrapKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
|
||||||
|
|
||||||
|
wrappedKeyBufferPtr =
|
||||||
|
(unsigned char*)wrappedKeySizeWrappedKeyArrayPtr +
|
||||||
|
sizeof(unsigned long);
|
||||||
|
rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism,
|
||||||
|
jLongToCKULong(jWrappingKeyHandle),ckObjectHandle,
|
||||||
|
wrappedKeyBufferPtr, &ckWrappedKeyLength);
|
||||||
|
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(wrappedKeySizeWrappedKeyArrayPtr, &ckWrappedKeyLength, sizeof(unsigned long));
|
||||||
|
TRACE1("DEBUG: GetNativeKeyInfo 2nd C_WrapKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
|
||||||
|
} else {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
returnValue = nativeKeyInfoWrappedKeyArray;
|
||||||
|
} else {
|
||||||
|
returnValue = nativeKeyInfoArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (ckpAttributes != NULL) {
|
||||||
|
free(ckpAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nativeKeyInfoArrayRaw != NULL) {
|
||||||
|
(*env)->ReleaseByteArrayElements(env, nativeKeyInfoArray,
|
||||||
|
nativeKeyInfoArrayRaw, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nativeKeyInfoWrappedKeyArrayRaw != NULL) {
|
||||||
|
(*env)->ReleaseByteArrayElements(env, nativeKeyInfoWrappedKeyArray,
|
||||||
|
nativeKeyInfoWrappedKeyArrayRaw, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nativeKeyInfoArray != NULL && returnValue != nativeKeyInfoArray) {
|
||||||
|
(*env)->DeleteLocalRef(env, nativeKeyInfoArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nativeKeyInfoWrappedKeyArray != NULL
|
||||||
|
&& returnValue != nativeKeyInfoWrappedKeyArray) {
|
||||||
|
(*env)->DeleteLocalRef(env, nativeKeyInfoWrappedKeyArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef P11_ENABLE_CREATENATIVEKEY
|
||||||
|
/*
|
||||||
|
* Class: sun_security_pkcs11_wrapper_PKCS11
|
||||||
|
* Method: createNativeKey
|
||||||
|
* Signature: (J[BJLsun/security/pkcs11/wrapper/CK_MECHANISM;)J
|
||||||
|
* Parametermapping: *PKCS11*
|
||||||
|
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
|
||||||
|
* @param jbyteArray jNativeKeyInfo -
|
||||||
|
* @param jlong jWrappingKeyHandle CK_OBJECT_HANDLE hObject
|
||||||
|
* @param jobject jWrappingMech CK_MECHANISM_PTR pMechanism
|
||||||
|
* @return jlong jKeyHandle CK_OBJECT_HANDLE hObject
|
||||||
|
*/
|
||||||
|
JNIEXPORT jlong JNICALL
|
||||||
|
Java_sun_security_pkcs11_wrapper_PKCS11_createNativeKey
|
||||||
|
(JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jNativeKeyInfo,
|
||||||
|
jlong jWrappingKeyHandle, jobject jWrappingMech)
|
||||||
|
{
|
||||||
|
CK_OBJECT_HANDLE ckObjectHandle;
|
||||||
|
CK_RV rv;
|
||||||
|
CK_SESSION_HANDLE ckSessionHandle = jLongToCKULong(jSessionHandle);
|
||||||
|
jbyte* nativeKeyInfoArrayRaw = NULL;
|
||||||
|
jlong jObjectHandle = 0L;
|
||||||
|
unsigned long totalCkAttributesSize = 0UL;
|
||||||
|
unsigned long nativeKeyInfoCkAttributesCount = 0UL;
|
||||||
|
jbyte* nativeKeyInfoArrayRawCkAttributes = NULL;
|
||||||
|
jbyte* nativeKeyInfoArrayRawCkAttributesPtr = NULL;
|
||||||
|
jbyte* nativeKeyInfoArrayRawDataPtr = NULL;
|
||||||
|
unsigned long totalDataSize = 0UL;
|
||||||
|
unsigned long* wrappedKeySizePtr = NULL;
|
||||||
|
unsigned int i = 0U;
|
||||||
|
CK_MECHANISM ckMechanism;
|
||||||
|
char iv[16] = {0x0};
|
||||||
|
CK_ULONG ckWrappedKeyLength = 0UL;
|
||||||
|
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
|
||||||
|
|
||||||
|
if (ckpFunctions == NULL) { goto cleanup; }
|
||||||
|
|
||||||
|
nativeKeyInfoArrayRaw =
|
||||||
|
(*env)->GetByteArrayElements(env, jNativeKeyInfo, NULL);
|
||||||
|
if (nativeKeyInfoArrayRaw == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&totalCkAttributesSize, nativeKeyInfoArrayRaw, sizeof(unsigned long));
|
||||||
|
TRACE1("DEBUG: createNativeKey totalCkAttributesSize = %lu\n", totalCkAttributesSize);
|
||||||
|
nativeKeyInfoCkAttributesCount = totalCkAttributesSize/sizeof(CK_ATTRIBUTE);
|
||||||
|
TRACE1("DEBUG: createNativeKey nativeKeyInfoCkAttributesCount = %lu\n", nativeKeyInfoCkAttributesCount);
|
||||||
|
|
||||||
|
nativeKeyInfoArrayRawCkAttributes = nativeKeyInfoArrayRaw +
|
||||||
|
sizeof(unsigned long);
|
||||||
|
nativeKeyInfoArrayRawCkAttributesPtr = nativeKeyInfoArrayRawCkAttributes;
|
||||||
|
nativeKeyInfoArrayRawDataPtr = nativeKeyInfoArrayRaw +
|
||||||
|
totalCkAttributesSize + sizeof(unsigned long) * 2;
|
||||||
|
memcpy(&totalDataSize, (nativeKeyInfoArrayRaw + totalCkAttributesSize + sizeof(unsigned long)),
|
||||||
|
sizeof(unsigned long));
|
||||||
|
TRACE1("DEBUG: createNativeKey totalDataSize = %lu\n", totalDataSize);
|
||||||
|
|
||||||
|
wrappedKeySizePtr = (unsigned long*)(nativeKeyInfoArrayRaw +
|
||||||
|
sizeof(unsigned long)*2 + totalCkAttributesSize + totalDataSize);
|
||||||
|
|
||||||
|
memcpy(&ckWrappedKeyLength, wrappedKeySizePtr, sizeof(unsigned long));
|
||||||
|
TRACE1("DEBUG: createNativeKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
|
||||||
|
|
||||||
|
for (i = 0; i < nativeKeyInfoCkAttributesCount; i++) {
|
||||||
|
if ((*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen
|
||||||
|
> 0) {
|
||||||
|
(*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue =
|
||||||
|
nativeKeyInfoArrayRawDataPtr;
|
||||||
|
}
|
||||||
|
nativeKeyInfoArrayRawDataPtr +=
|
||||||
|
(*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen;
|
||||||
|
nativeKeyInfoArrayRawCkAttributesPtr += sizeof(CK_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ckWrappedKeyLength == 0) {
|
||||||
|
// Not a wrapped key
|
||||||
|
rv = (*ckpFunctions->C_CreateObject)(ckSessionHandle,
|
||||||
|
(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
|
||||||
|
jLongToCKULong(nativeKeyInfoCkAttributesCount), &ckObjectHandle);
|
||||||
|
} else {
|
||||||
|
// Wrapped key
|
||||||
|
jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism);
|
||||||
|
rv = (*ckpFunctions->C_UnwrapKey)(ckSessionHandle, &ckMechanism,
|
||||||
|
jLongToCKULong(jWrappingKeyHandle),
|
||||||
|
(CK_BYTE_PTR)(wrappedKeySizePtr + 1), ckWrappedKeyLength,
|
||||||
|
(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
|
||||||
|
jLongToCKULong(nativeKeyInfoCkAttributesCount),
|
||||||
|
&ckObjectHandle);
|
||||||
|
}
|
||||||
|
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
jObjectHandle = ckULongToJLong(ckObjectHandle);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
if (nativeKeyInfoArrayRaw != NULL) {
|
||||||
|
(*env)->ReleaseByteArrayElements(env, jNativeKeyInfo,
|
||||||
|
nativeKeyInfoArrayRaw, JNI_ABORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jObjectHandle;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef P11_ENABLE_C_GENERATEKEY
|
#ifdef P11_ENABLE_C_GENERATEKEY
|
||||||
/*
|
/*
|
||||||
* Class: sun_security_pkcs11_wrapper_PKCS11
|
* Class: sun_security_pkcs11_wrapper_PKCS11
|
||||||
|
@ -548,6 +548,7 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE;
|
|||||||
#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
|
#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
|
||||||
|
|
||||||
#define CKA_VENDOR_DEFINED 0x80000000
|
#define CKA_VENDOR_DEFINED 0x80000000
|
||||||
|
#define CKA_NETSCAPE_DB 0xD5A0DB00
|
||||||
|
|
||||||
|
|
||||||
/* CK_ATTRIBUTE is a structure that includes the type, length
|
/* CK_ATTRIBUTE is a structure that includes the type, length
|
||||||
|
@ -151,6 +151,8 @@
|
|||||||
#undef P11_ENABLE_C_GETFUNCTIONSTATUS
|
#undef P11_ENABLE_C_GETFUNCTIONSTATUS
|
||||||
#undef P11_ENABLE_C_CANCELFUNCTION
|
#undef P11_ENABLE_C_CANCELFUNCTION
|
||||||
#undef P11_ENABLE_C_WAITFORSLOTEVENT
|
#undef P11_ENABLE_C_WAITFORSLOTEVENT
|
||||||
|
#define P11_ENABLE_GETNATIVEKEYINFO
|
||||||
|
#define P11_ENABLE_CREATENATIVEKEY
|
||||||
|
|
||||||
/* include the platform dependent part of the header */
|
/* include the platform dependent part of the header */
|
||||||
#include "p11_md.h"
|
#include "p11_md.h"
|
||||||
@ -204,6 +206,8 @@
|
|||||||
#define ckULongToJSize(x) ((jsize) x)
|
#define ckULongToJSize(x) ((jsize) x)
|
||||||
#define unsignedIntToCKULong(x) ((CK_ULONG) x)
|
#define unsignedIntToCKULong(x) ((CK_ULONG) x)
|
||||||
|
|
||||||
|
//#define P11_DEBUG
|
||||||
|
|
||||||
#ifdef P11_DEBUG
|
#ifdef P11_DEBUG
|
||||||
#define TRACE0(s) { printf(s); fflush(stdout); }
|
#define TRACE0(s) { printf(s); fflush(stdout); }
|
||||||
#define TRACE1(s, p1) { printf(s, p1); fflush(stdout); }
|
#define TRACE1(s, p1) { printf(s, p1); fflush(stdout); }
|
||||||
|
Loading…
Reference in New Issue
Block a user