8236512: PKCS11 Connection closed after Cipher.doFinal and NoPadding

Removed killSession() calls in certain impl classes when cancelling operations

Reviewed-by: xuelei
This commit is contained in:
Valerie Peng 2020-02-12 00:56:27 +00:00
parent c37ebcd730
commit 1f17842583
6 changed files with 128 additions and 135 deletions

View File

@ -1,4 +1,5 @@
/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. /*
* Copyright (c) 2019, 2020, 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
@ -332,25 +333,25 @@ final class P11AEADCipher extends CipherSpi {
} }
private void cancelOperation() { private void cancelOperation() {
// cancel operation by finishing it; avoid killSession as some
// hardware vendors may require re-login
int bufLen = doFinalLength(0);
byte[] buffer = new byte[bufLen];
byte[] in = dataBuffer.toByteArray();
int inLen = in.length;
try { try {
if (session.hasObjects() == false) { if (encrypt) {
session = token.killSession(session); token.p11.C_Encrypt(session.id(), 0, in, 0, inLen,
return; 0, buffer, 0, bufLen);
} else { } else {
// cancel operation by finishing it token.p11.C_Decrypt(session.id(), 0, in, 0, inLen,
int bufLen = doFinalLength(0); 0, buffer, 0, bufLen);
byte[] buffer = new byte[bufLen];
if (encrypt) {
token.p11.C_Encrypt(session.id(), 0, buffer, 0, bufLen,
0, buffer, 0, bufLen);
} else {
token.p11.C_Decrypt(session.id(), 0, buffer, 0, bufLen,
0, buffer, 0, bufLen);
}
} }
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
throw new ProviderException("Cancel failed", e); if (encrypt) {
throw new ProviderException("Cancel failed", e);
}
// ignore failure for decryption
} }
} }
@ -432,18 +433,21 @@ final class P11AEADCipher extends CipherSpi {
if (!initialized) { if (!initialized) {
return; return;
} }
initialized = false;
try { try {
if (session == null) { if (session == null) {
return; return;
} }
if (doCancel && token.explicitCancel) { if (doCancel && token.explicitCancel) {
cancelOperation(); cancelOperation();
} }
} finally { } finally {
p11Key.releaseKeyID(); p11Key.releaseKeyID();
session = token.releaseSession(session); session = token.releaseSession(session);
dataBuffer.reset();
} }
initialized = false;
} }
// see JCE spec // see JCE spec

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, 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
@ -407,10 +407,12 @@ final class P11Cipher extends CipherSpi {
return; return;
} }
initialized = false; initialized = false;
try { try {
if (session == null) { if (session == null) {
return; return;
} }
if (doCancel && token.explicitCancel) { if (doCancel && token.explicitCancel) {
cancelOperation(); cancelOperation();
} }
@ -424,22 +426,21 @@ final class P11Cipher extends CipherSpi {
private void cancelOperation() { private void cancelOperation() {
token.ensureValid(); token.ensureValid();
if (session.hasObjects() == false) { // cancel operation by finishing it; avoid killSession as some
session = token.killSession(session); // hardware vendors may require re-login
return; try {
} else { int bufLen = doFinalLength(0);
try { byte[] buffer = new byte[bufLen];
// cancel operation by finishing it if (encrypt) {
int bufLen = doFinalLength(0); token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
byte[] buffer = new byte[bufLen]; } else {
if (encrypt) { token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen); }
} else { } catch (PKCS11Exception e) {
token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen); if (encrypt) {
}
} catch (PKCS11Exception e) {
throw new ProviderException("Cancel failed", e); throw new ProviderException("Cancel failed", e);
} }
// ignore failure for decryption
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, 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
@ -124,10 +124,12 @@ final class P11Mac extends MacSpi {
return; return;
} }
initialized = false; initialized = false;
try { try {
if (session == null) { if (session == null) {
return; return;
} }
if (doCancel && token.explicitCancel) { if (doCancel && token.explicitCancel) {
cancelOperation(); cancelOperation();
} }
@ -139,15 +141,12 @@ final class P11Mac extends MacSpi {
private void cancelOperation() { private void cancelOperation() {
token.ensureValid(); token.ensureValid();
if (session.hasObjects() == false) { // cancel operation by finishing it; avoid killSession as some
session = token.killSession(session); // hardware vendors may require re-login
return; try {
} else { token.p11.C_SignFinal(session.id(), 0);
try { } catch (PKCS11Exception e) {
token.p11.C_SignFinal(session.id(), 0); throw new ProviderException("Cancel failed", e);
} catch (PKCS11Exception e) {
throw new ProviderException("Cancel failed", e);
}
} }
} }
@ -209,7 +208,6 @@ final class P11Mac extends MacSpi {
ensureInitialized(); ensureInitialized();
return token.p11.C_SignFinal(session.id(), 0); return token.p11.C_SignFinal(session.id(), 0);
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
reset(true);
throw new ProviderException("doFinal() failed", e); throw new ProviderException("doFinal() failed", e);
} finally { } finally {
reset(false); reset(false);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, 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
@ -223,10 +223,12 @@ final class P11PSSSignature extends SignatureSpi {
return; return;
} }
initialized = false; initialized = false;
try { try {
if (session == null) { if (session == null) {
return; return;
} }
if (doCancel && token.explicitCancel) { if (doCancel && token.explicitCancel) {
cancelOperation(); cancelOperation();
} }
@ -242,14 +244,10 @@ final class P11PSSSignature extends SignatureSpi {
token.ensureValid(); token.ensureValid();
if (DEBUG) System.out.print("Cancelling operation"); if (DEBUG) System.out.print("Cancelling operation");
if (session.hasObjects() == false) { // cancel operation by finishing it; avoid killSession as some
if (DEBUG) System.out.println(" by killing session"); // hardware vendors may require re-login
session = token.killSession(session); try {
return; if (mode == M_SIGN) {
}
// "cancel" operation by finishing it
if (mode == M_SIGN) {
try {
if (type == T_UPDATE) { if (type == T_UPDATE) {
if (DEBUG) System.out.println(" by C_SignFinal"); if (DEBUG) System.out.println(" by C_SignFinal");
token.p11.C_SignFinal(session.id(), 0); token.p11.C_SignFinal(session.id(), 0);
@ -259,11 +257,7 @@ final class P11PSSSignature extends SignatureSpi {
if (DEBUG) System.out.println(" by C_Sign"); if (DEBUG) System.out.println(" by C_Sign");
token.p11.C_Sign(session.id(), digest); token.p11.C_Sign(session.id(), digest);
} }
} catch (PKCS11Exception e) { } else { // M_VERIFY
throw new ProviderException("cancel failed", e);
}
} else { // M_VERIFY
try {
byte[] signature = byte[] signature =
new byte[(p11Key.length() + 7) >> 3]; new byte[(p11Key.length() + 7) >> 3];
if (type == T_UPDATE) { if (type == T_UPDATE) {
@ -275,10 +269,12 @@ final class P11PSSSignature extends SignatureSpi {
if (DEBUG) System.out.println(" by C_Verify"); if (DEBUG) System.out.println(" by C_Verify");
token.p11.C_Verify(session.id(), digest, signature); token.p11.C_Verify(session.id(), digest, signature);
} }
} catch (PKCS11Exception e) {
// will fail since the signature is incorrect
// XXX check error code
} }
} catch (PKCS11Exception e) {
if (mode == M_SIGN) {
throw new ProviderException("cancel failed", e);
}
// ignore failure for verification
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, 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
@ -247,10 +247,12 @@ final class P11RSACipher extends CipherSpi {
return; return;
} }
initialized = false; initialized = false;
try { try {
if (session == null) { if (session == null) {
return; return;
} }
if (doCancel && token.explicitCancel) { if (doCancel && token.explicitCancel) {
cancelOperation(); cancelOperation();
} }
@ -264,36 +266,33 @@ final class P11RSACipher extends CipherSpi {
// state variables such as "initialized" // state variables such as "initialized"
private void cancelOperation() { private void cancelOperation() {
token.ensureValid(); token.ensureValid();
if (session.hasObjects() == false) { // cancel operation by finishing it; avoid killSession as some
session = token.killSession(session); // hardware vendors may require re-login
return; try {
} else { PKCS11 p11 = token.p11;
try { int inLen = maxInputSize;
PKCS11 p11 = token.p11; int outLen = buffer.length;
int inLen = maxInputSize; long sessId = session.id();
int outLen = buffer.length; switch (mode) {
long sessId = session.id(); case MODE_ENCRYPT:
switch (mode) { p11.C_Encrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen);
case MODE_ENCRYPT: break;
p11.C_Encrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); case MODE_DECRYPT:
break; p11.C_Decrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen);
case MODE_DECRYPT: break;
p11.C_Decrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); case MODE_SIGN:
break; byte[] tmpBuffer = new byte[maxInputSize];
case MODE_SIGN: p11.C_Sign(sessId, tmpBuffer);
byte[] tmpBuffer = new byte[maxInputSize]; break;
p11.C_Sign(sessId, tmpBuffer); case MODE_VERIFY:
break; p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer,
case MODE_VERIFY: 0, outLen);
p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer, break;
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
} }
} }
@ -362,6 +361,7 @@ final class P11RSACipher extends CipherSpi {
private int implDoFinal(byte[] out, int outOfs, int outLen) private int implDoFinal(byte[] out, int outOfs, int outLen)
throws BadPaddingException, IllegalBlockSizeException { throws BadPaddingException, IllegalBlockSizeException {
if (bufOfs > maxInputSize) { if (bufOfs > maxInputSize) {
reset(true);
throw new IllegalBlockSizeException("Data must not be longer " throw new IllegalBlockSizeException("Data must not be longer "
+ "than " + maxInputSize + " bytes"); + "than " + maxInputSize + " bytes");
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, 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
@ -270,10 +270,12 @@ final class P11Signature extends SignatureSpi {
return; return;
} }
initialized = false; initialized = false;
try { try {
if (session == null) { if (session == null) {
return; return;
} }
if (doCancel && token.explicitCancel) { if (doCancel && token.explicitCancel) {
cancelOperation(); cancelOperation();
} }
@ -284,59 +286,51 @@ final class P11Signature extends SignatureSpi {
} }
private void cancelOperation() { private void cancelOperation() {
token.ensureValid(); token.ensureValid();
if (session.hasObjects() == false) { // cancel operation by finishing it; avoid killSession as some
session = token.killSession(session); // hardware vendors may require re-login
return; try {
} else {
// "cancel" operation by finishing it
// XXX make sure all this always works correctly
if (mode == M_SIGN) { if (mode == M_SIGN) {
try { if (type == T_UPDATE) {
if (type == T_UPDATE) { token.p11.C_SignFinal(session.id(), 0);
token.p11.C_SignFinal(session.id(), 0); } else {
} else { byte[] digest;
byte[] digest; if (type == T_DIGEST) {
if (type == T_DIGEST) { digest = md.digest();
digest = md.digest(); } else { // T_RAW
} else { // T_RAW digest = buffer;
digest = buffer;
}
token.p11.C_Sign(session.id(), digest);
} }
} catch (PKCS11Exception e) { token.p11.C_Sign(session.id(), digest);
throw new ProviderException("cancel failed", e);
} }
} else { // M_VERIFY } else { // M_VERIFY
byte[] signature; byte[] signature;
try { if (keyAlgorithm.equals("DSA")) {
if (keyAlgorithm.equals("DSA")) { signature = new byte[40];
signature = new byte[40]; } else {
} else { signature = new byte[(p11Key.length() + 7) >> 3];
signature = new byte[(p11Key.length() + 7) >> 3]; }
if (type == T_UPDATE) {
token.p11.C_VerifyFinal(session.id(), signature);
} else {
byte[] digest;
if (type == T_DIGEST) {
digest = md.digest();
} else { // T_RAW
digest = buffer;
} }
if (type == T_UPDATE) { token.p11.C_Verify(session.id(), digest, signature);
token.p11.C_VerifyFinal(session.id(), signature);
} else {
byte[] digest;
if (type == T_DIGEST) {
digest = md.digest();
} else { // T_RAW
digest = buffer;
}
token.p11.C_Verify(session.id(), digest, signature);
}
} catch (PKCS11Exception e) {
long errorCode = e.getErrorCode();
if ((errorCode == CKR_SIGNATURE_INVALID) ||
(errorCode == CKR_SIGNATURE_LEN_RANGE)) {
// expected since signature is incorrect
return;
}
throw new ProviderException("cancel failed", e);
} }
} }
} catch (PKCS11Exception e) {
if (mode == M_VERIFY) {
long errorCode = e.getErrorCode();
if ((errorCode == CKR_SIGNATURE_INVALID) ||
(errorCode == CKR_SIGNATURE_LEN_RANGE)) {
// expected since signature is incorrect
return;
}
}
throw new ProviderException("cancel failed", e);
} }
} }