# HG changeset patch # User valeriep # Date 1581468987 0 # Wed Feb 12 00:56:27 2020 +0000 # Node ID e47d22d82b0464720ccb7641e290080972b6ce88 # Parent 5c41dc4c48f85e5a1e1ce6e3836b54674f273367 8236512: PKCS11 Connection closed after Cipher.doFinal and NoPadding Summary: Removed killSession() calls in certain impl classes when cancelling operations Reviewed-by: xuelei diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -334,25 +335,25 @@ } private void cancelOperation() { + // cancel operation by finishing it; avoid killSession as some + // hardware vendors may require re-login + int bufLen = doFinalLength(0); + byte[] buffer = new byte[bufLen]; + byte[] in = dataBuffer.toByteArray(); + int inLen = in.length; try { - if (session.hasObjects() == false) { - session = token.killSession(session); - return; + if (encrypt) { + token.p11.C_Encrypt(session.id(), 0, in, 0, inLen, + 0, buffer, 0, bufLen); } else { - // cancel operation by finishing it - int bufLen = doFinalLength(0); - 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); - } + token.p11.C_Decrypt(session.id(), 0, in, 0, inLen, + 0, buffer, 0, bufLen); } } catch (PKCS11Exception e) { - throw new ProviderException("Cancel failed", e); + if (encrypt) { + throw new ProviderException("Cancel failed", e); + } + // ignore failure for decryption } } @@ -434,18 +435,21 @@ if (!initialized) { return; } + initialized = false; + try { if (session == null) { return; } + if (doCancel && token.explicitCancel) { cancelOperation(); } } finally { p11Key.releaseKeyID(); session = token.releaseSession(session); + dataBuffer.reset(); } - initialized = false; } // see JCE spec diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -409,10 +409,12 @@ return; } initialized = false; + try { if (session == null) { return; } + if (doCancel && token.explicitCancel) { cancelOperation(); } @@ -426,22 +428,21 @@ private void cancelOperation() { token.ensureValid(); - if (session.hasObjects() == false) { - session = token.killSession(session); - return; - } else { - try { - // cancel operation by finishing it - int bufLen = doFinalLength(0); - byte[] buffer = new byte[bufLen]; - if (encrypt) { - token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen); - } else { - token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen); - } - } catch (PKCS11Exception e) { + // cancel operation by finishing it; avoid killSession as some + // hardware vendors may require re-login + try { + int bufLen = doFinalLength(0); + byte[] buffer = new byte[bufLen]; + if (encrypt) { + token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen); + } else { + token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen); + } + } catch (PKCS11Exception e) { + if (encrypt) { throw new ProviderException("Cancel failed", e); } + // ignore failure for decryption } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -124,10 +124,12 @@ return; } initialized = false; + try { if (session == null) { return; } + if (doCancel && token.explicitCancel) { cancelOperation(); } @@ -139,15 +141,12 @@ private void cancelOperation() { token.ensureValid(); - if (session.hasObjects() == false) { - session = token.killSession(session); - return; - } else { - try { - token.p11.C_SignFinal(session.id(), 0); - } catch (PKCS11Exception e) { - throw new ProviderException("Cancel failed", e); - } + // cancel operation by finishing it; avoid killSession as some + // hardware vendors may require re-login + try { + token.p11.C_SignFinal(session.id(), 0); + } catch (PKCS11Exception e) { + throw new ProviderException("Cancel failed", e); } } @@ -209,7 +208,6 @@ ensureInitialized(); return token.p11.C_SignFinal(session.id(), 0); } catch (PKCS11Exception e) { - reset(true); throw new ProviderException("doFinal() failed", e); } finally { reset(false); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -223,10 +223,12 @@ return; } initialized = false; + try { if (session == null) { return; } + if (doCancel && token.explicitCancel) { cancelOperation(); } @@ -242,14 +244,10 @@ token.ensureValid(); if (DEBUG) System.out.print("Cancelling operation"); - if (session.hasObjects() == false) { - if (DEBUG) System.out.println(" by killing session"); - session = token.killSession(session); - return; - } - // "cancel" operation by finishing it - if (mode == M_SIGN) { - try { + // cancel operation by finishing it; avoid killSession as some + // hardware vendors may require re-login + try { + if (mode == M_SIGN) { if (type == T_UPDATE) { if (DEBUG) System.out.println(" by C_SignFinal"); token.p11.C_SignFinal(session.id(), 0); @@ -259,11 +257,7 @@ if (DEBUG) System.out.println(" by C_Sign"); token.p11.C_Sign(session.id(), digest); } - } catch (PKCS11Exception e) { - throw new ProviderException("cancel failed", e); - } - } else { // M_VERIFY - try { + } else { // M_VERIFY byte[] signature = new byte[(p11Key.length() + 7) >> 3]; if (type == T_UPDATE) { @@ -275,10 +269,12 @@ if (DEBUG) System.out.println(" by C_Verify"); 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 } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -247,10 +247,12 @@ return; } initialized = false; + try { if (session == null) { return; } + if (doCancel && token.explicitCancel) { cancelOperation(); } @@ -264,36 +266,33 @@ // state variables such as "initialized" private void cancelOperation() { token.ensureValid(); - if (session.hasObjects() == false) { - session = token.killSession(session); - return; - } else { - try { - PKCS11 p11 = token.p11; - int inLen = maxInputSize; - int outLen = buffer.length; - long sessId = session.id(); - switch (mode) { - case MODE_ENCRYPT: - p11.C_Encrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); - break; - case MODE_DECRYPT: - p11.C_Decrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); - break; - case MODE_SIGN: - byte[] tmpBuffer = new byte[maxInputSize]; - p11.C_Sign(sessId, tmpBuffer); - break; - case MODE_VERIFY: - p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer, - 0, outLen); - break; - default: - throw new ProviderException("internal error"); - } - } catch (PKCS11Exception e) { - // XXX ensure this always works, ignore error + // cancel operation by finishing it; avoid killSession as some + // hardware vendors may require re-login + try { + PKCS11 p11 = token.p11; + int inLen = maxInputSize; + int outLen = buffer.length; + long sessId = session.id(); + switch (mode) { + case MODE_ENCRYPT: + p11.C_Encrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); + break; + case MODE_DECRYPT: + p11.C_Decrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); + break; + case MODE_SIGN: + byte[] tmpBuffer = new byte[maxInputSize]; + p11.C_Sign(sessId, tmpBuffer); + break; + case MODE_VERIFY: + p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer, + 0, outLen); + break; + default: + throw new ProviderException("internal error"); } + } catch (PKCS11Exception e) { + // XXX ensure this always works, ignore error } } @@ -362,6 +361,7 @@ private int implDoFinal(byte[] out, int outOfs, int outLen) throws BadPaddingException, IllegalBlockSizeException { if (bufOfs > maxInputSize) { + reset(true); throw new IllegalBlockSizeException("Data must not be longer " + "than " + maxInputSize + " bytes"); } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -270,10 +270,12 @@ return; } initialized = false; + try { if (session == null) { return; } + if (doCancel && token.explicitCancel) { cancelOperation(); } @@ -284,59 +286,51 @@ } private void cancelOperation() { - token.ensureValid(); - if (session.hasObjects() == false) { - session = token.killSession(session); - return; - } else { - // "cancel" operation by finishing it - // XXX make sure all this always works correctly + // cancel operation by finishing it; avoid killSession as some + // hardware vendors may require re-login + try { if (mode == M_SIGN) { - try { - if (type == T_UPDATE) { - token.p11.C_SignFinal(session.id(), 0); - } else { - byte[] digest; - if (type == T_DIGEST) { - digest = md.digest(); - } else { // T_RAW - digest = buffer; - } - token.p11.C_Sign(session.id(), digest); + if (type == T_UPDATE) { + token.p11.C_SignFinal(session.id(), 0); + } else { + byte[] digest; + if (type == T_DIGEST) { + digest = md.digest(); + } else { // T_RAW + digest = buffer; } - } catch (PKCS11Exception e) { - throw new ProviderException("cancel failed", e); + token.p11.C_Sign(session.id(), digest); } } else { // M_VERIFY byte[] signature; - try { - if (keyAlgorithm.equals("DSA")) { - signature = new byte[40]; - } else { - signature = new byte[(p11Key.length() + 7) >> 3]; + if (keyAlgorithm.equals("DSA")) { + signature = new byte[40]; + } else { + signature = new byte[(p11Key.length() + 7) >> 3]; + } + if (type == T_UPDATE) { + token.p11.C_VerifyFinal(session.id(), signature); + } else { + byte[] digest; + if (type == T_DIGEST) { + digest = md.digest(); + } else { // T_RAW + digest = buffer; } - if (type == T_UPDATE) { - token.p11.C_VerifyFinal(session.id(), signature); - } else { - byte[] digest; - if (type == T_DIGEST) { - digest = md.digest(); - } else { // T_RAW - digest = buffer; - } - token.p11.C_Verify(session.id(), digest, signature); - } - } catch (PKCS11Exception e) { - 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); + token.p11.C_Verify(session.id(), digest, signature); } } + } 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); } }