Fri, 30 Oct 2020 07:09:00 +0000
8236512: PKCS11 Connection closed after Cipher.doFinal and NoPadding
Summary: Removed killSession() calls in certain impl classes when cancelling operations
Reviewed-by: xuelei
1.1 --- a/src/share/classes/sun/security/pkcs11/P11AEADCipher.java Wed Nov 06 09:45:04 2019 -0800 1.2 +++ b/src/share/classes/sun/security/pkcs11/P11AEADCipher.java Fri Oct 30 07:09:00 2020 +0000 1.3 @@ -1,4 +1,5 @@ 1.4 -/* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 1.5 +/* 1.6 + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -331,25 +332,25 @@ 1.11 } 1.12 1.13 private void cancelOperation() { 1.14 + // cancel operation by finishing it; avoid killSession as some 1.15 + // hardware vendors may require re-login 1.16 + int bufLen = doFinalLength(0); 1.17 + byte[] buffer = new byte[bufLen]; 1.18 + byte[] in = dataBuffer.toByteArray(); 1.19 + int inLen = in.length; 1.20 try { 1.21 - if (session.hasObjects() == false) { 1.22 - session = token.killSession(session); 1.23 - return; 1.24 + if (encrypt) { 1.25 + token.p11.C_Encrypt(session.id(), 0, in, 0, inLen, 1.26 + 0, buffer, 0, bufLen); 1.27 } else { 1.28 - // cancel operation by finishing it 1.29 - int bufLen = doFinalLength(0); 1.30 - byte[] buffer = new byte[bufLen]; 1.31 - 1.32 - if (encrypt) { 1.33 - token.p11.C_Encrypt(session.id(), 0, buffer, 0, bufLen, 1.34 - 0, buffer, 0, bufLen); 1.35 - } else { 1.36 - token.p11.C_Decrypt(session.id(), 0, buffer, 0, bufLen, 1.37 - 0, buffer, 0, bufLen); 1.38 - } 1.39 + token.p11.C_Decrypt(session.id(), 0, in, 0, inLen, 1.40 + 0, buffer, 0, bufLen); 1.41 } 1.42 } catch (PKCS11Exception e) { 1.43 - throw new ProviderException("Cancel failed", e); 1.44 + if (encrypt) { 1.45 + throw new ProviderException("Cancel failed", e); 1.46 + } 1.47 + // ignore failure for decryption 1.48 } 1.49 } 1.50 1.51 @@ -432,18 +433,21 @@ 1.52 if (!initialized) { 1.53 return; 1.54 } 1.55 + initialized = false; 1.56 + 1.57 try { 1.58 if (session == null) { 1.59 return; 1.60 } 1.61 + 1.62 if (doCancel && token.explicitCancel) { 1.63 cancelOperation(); 1.64 } 1.65 } finally { 1.66 p11Key.releaseKeyID(); 1.67 session = token.releaseSession(session); 1.68 + dataBuffer.reset(); 1.69 } 1.70 - initialized = false; 1.71 } 1.72 1.73 // see JCE spec
2.1 --- a/src/share/classes/sun/security/pkcs11/P11Cipher.java Wed Nov 06 09:45:04 2019 -0800 2.2 +++ b/src/share/classes/sun/security/pkcs11/P11Cipher.java Fri Oct 30 07:09:00 2020 +0000 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -409,10 +409,12 @@ 2.11 return; 2.12 } 2.13 initialized = false; 2.14 + 2.15 try { 2.16 if (session == null) { 2.17 return; 2.18 } 2.19 + 2.20 if (doCancel && token.explicitCancel) { 2.21 cancelOperation(); 2.22 } 2.23 @@ -426,22 +428,21 @@ 2.24 2.25 private void cancelOperation() { 2.26 token.ensureValid(); 2.27 - if (session.hasObjects() == false) { 2.28 - session = token.killSession(session); 2.29 - return; 2.30 - } else { 2.31 - try { 2.32 - // cancel operation by finishing it 2.33 - int bufLen = doFinalLength(0); 2.34 - byte[] buffer = new byte[bufLen]; 2.35 - if (encrypt) { 2.36 - token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen); 2.37 - } else { 2.38 - token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen); 2.39 - } 2.40 - } catch (PKCS11Exception e) { 2.41 + // cancel operation by finishing it; avoid killSession as some 2.42 + // hardware vendors may require re-login 2.43 + try { 2.44 + int bufLen = doFinalLength(0); 2.45 + byte[] buffer = new byte[bufLen]; 2.46 + if (encrypt) { 2.47 + token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen); 2.48 + } else { 2.49 + token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen); 2.50 + } 2.51 + } catch (PKCS11Exception e) { 2.52 + if (encrypt) { 2.53 throw new ProviderException("Cancel failed", e); 2.54 } 2.55 + // ignore failure for decryption 2.56 } 2.57 } 2.58
3.1 --- a/src/share/classes/sun/security/pkcs11/P11Mac.java Wed Nov 06 09:45:04 2019 -0800 3.2 +++ b/src/share/classes/sun/security/pkcs11/P11Mac.java Fri Oct 30 07:09:00 2020 +0000 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -122,10 +122,12 @@ 3.11 return; 3.12 } 3.13 initialized = false; 3.14 + 3.15 try { 3.16 if (session == null) { 3.17 return; 3.18 } 3.19 + 3.20 if (doCancel && token.explicitCancel) { 3.21 cancelOperation(); 3.22 } 3.23 @@ -137,15 +139,12 @@ 3.24 3.25 private void cancelOperation() { 3.26 token.ensureValid(); 3.27 - if (session.hasObjects() == false) { 3.28 - session = token.killSession(session); 3.29 - return; 3.30 - } else { 3.31 - try { 3.32 - token.p11.C_SignFinal(session.id(), 0); 3.33 - } catch (PKCS11Exception e) { 3.34 - throw new ProviderException("Cancel failed", e); 3.35 - } 3.36 + // cancel operation by finishing it; avoid killSession as some 3.37 + // hardware vendors may require re-login 3.38 + try { 3.39 + token.p11.C_SignFinal(session.id(), 0); 3.40 + } catch (PKCS11Exception e) { 3.41 + throw new ProviderException("Cancel failed", e); 3.42 } 3.43 } 3.44 3.45 @@ -207,7 +206,6 @@ 3.46 ensureInitialized(); 3.47 return token.p11.C_SignFinal(session.id(), 0); 3.48 } catch (PKCS11Exception e) { 3.49 - reset(true); 3.50 throw new ProviderException("doFinal() failed", e); 3.51 } finally { 3.52 reset(false);
4.1 --- a/src/share/classes/sun/security/pkcs11/P11PSSSignature.java Wed Nov 06 09:45:04 2019 -0800 4.2 +++ b/src/share/classes/sun/security/pkcs11/P11PSSSignature.java Fri Oct 30 07:09:00 2020 +0000 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 4.6 + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. 4.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 * 4.9 * This code is free software; you can redistribute it and/or modify it 4.10 @@ -223,10 +223,12 @@ 4.11 return; 4.12 } 4.13 initialized = false; 4.14 + 4.15 try { 4.16 if (session == null) { 4.17 return; 4.18 } 4.19 + 4.20 if (doCancel && token.explicitCancel) { 4.21 cancelOperation(); 4.22 } 4.23 @@ -242,14 +244,10 @@ 4.24 token.ensureValid(); 4.25 if (DEBUG) System.out.print("Cancelling operation"); 4.26 4.27 - if (session.hasObjects() == false) { 4.28 - if (DEBUG) System.out.println(" by killing session"); 4.29 - session = token.killSession(session); 4.30 - return; 4.31 - } 4.32 - // "cancel" operation by finishing it 4.33 - if (mode == M_SIGN) { 4.34 - try { 4.35 + // cancel operation by finishing it; avoid killSession as some 4.36 + // hardware vendors may require re-login 4.37 + try { 4.38 + if (mode == M_SIGN) { 4.39 if (type == T_UPDATE) { 4.40 if (DEBUG) System.out.println(" by C_SignFinal"); 4.41 token.p11.C_SignFinal(session.id(), 0); 4.42 @@ -259,11 +257,7 @@ 4.43 if (DEBUG) System.out.println(" by C_Sign"); 4.44 token.p11.C_Sign(session.id(), digest); 4.45 } 4.46 - } catch (PKCS11Exception e) { 4.47 - throw new ProviderException("cancel failed", e); 4.48 - } 4.49 - } else { // M_VERIFY 4.50 - try { 4.51 + } else { // M_VERIFY 4.52 byte[] signature = 4.53 new byte[(p11Key.length() + 7) >> 3]; 4.54 if (type == T_UPDATE) { 4.55 @@ -275,10 +269,12 @@ 4.56 if (DEBUG) System.out.println(" by C_Verify"); 4.57 token.p11.C_Verify(session.id(), digest, signature); 4.58 } 4.59 - } catch (PKCS11Exception e) { 4.60 - // will fail since the signature is incorrect 4.61 - // XXX check error code 4.62 } 4.63 + } catch (PKCS11Exception e) { 4.64 + if (mode == M_SIGN) { 4.65 + throw new ProviderException("cancel failed", e); 4.66 + } 4.67 + // ignore failure for verification 4.68 } 4.69 } 4.70
5.1 --- a/src/share/classes/sun/security/pkcs11/P11RSACipher.java Wed Nov 06 09:45:04 2019 -0800 5.2 +++ b/src/share/classes/sun/security/pkcs11/P11RSACipher.java Fri Oct 30 07:09:00 2020 +0000 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -246,10 +246,12 @@ 5.11 return; 5.12 } 5.13 initialized = false; 5.14 + 5.15 try { 5.16 if (session == null) { 5.17 return; 5.18 } 5.19 + 5.20 if (doCancel && token.explicitCancel) { 5.21 cancelOperation(); 5.22 } 5.23 @@ -263,36 +265,33 @@ 5.24 // state variables such as "initialized" 5.25 private void cancelOperation() { 5.26 token.ensureValid(); 5.27 - if (session.hasObjects() == false) { 5.28 - session = token.killSession(session); 5.29 - return; 5.30 - } else { 5.31 - try { 5.32 - PKCS11 p11 = token.p11; 5.33 - int inLen = maxInputSize; 5.34 - int outLen = buffer.length; 5.35 - long sessId = session.id(); 5.36 - switch (mode) { 5.37 - case MODE_ENCRYPT: 5.38 - p11.C_Encrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); 5.39 - break; 5.40 - case MODE_DECRYPT: 5.41 - p11.C_Decrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); 5.42 - break; 5.43 - case MODE_SIGN: 5.44 - byte[] tmpBuffer = new byte[maxInputSize]; 5.45 - p11.C_Sign(sessId, tmpBuffer); 5.46 - break; 5.47 - case MODE_VERIFY: 5.48 - p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer, 5.49 - 0, outLen); 5.50 - break; 5.51 - default: 5.52 - throw new ProviderException("internal error"); 5.53 - } 5.54 - } catch (PKCS11Exception e) { 5.55 - // XXX ensure this always works, ignore error 5.56 + // cancel operation by finishing it; avoid killSession as some 5.57 + // hardware vendors may require re-login 5.58 + try { 5.59 + PKCS11 p11 = token.p11; 5.60 + int inLen = maxInputSize; 5.61 + int outLen = buffer.length; 5.62 + long sessId = session.id(); 5.63 + switch (mode) { 5.64 + case MODE_ENCRYPT: 5.65 + p11.C_Encrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); 5.66 + break; 5.67 + case MODE_DECRYPT: 5.68 + p11.C_Decrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen); 5.69 + break; 5.70 + case MODE_SIGN: 5.71 + byte[] tmpBuffer = new byte[maxInputSize]; 5.72 + p11.C_Sign(sessId, tmpBuffer); 5.73 + break; 5.74 + case MODE_VERIFY: 5.75 + p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer, 5.76 + 0, outLen); 5.77 + break; 5.78 + default: 5.79 + throw new ProviderException("internal error"); 5.80 } 5.81 + } catch (PKCS11Exception e) { 5.82 + // XXX ensure this always works, ignore error 5.83 } 5.84 } 5.85 5.86 @@ -361,6 +360,7 @@ 5.87 private int implDoFinal(byte[] out, int outOfs, int outLen) 5.88 throws BadPaddingException, IllegalBlockSizeException { 5.89 if (bufOfs > maxInputSize) { 5.90 + reset(true); 5.91 throw new IllegalBlockSizeException("Data must not be longer " 5.92 + "than " + maxInputSize + " bytes"); 5.93 }
6.1 --- a/src/share/classes/sun/security/pkcs11/P11Signature.java Wed Nov 06 09:45:04 2019 -0800 6.2 +++ b/src/share/classes/sun/security/pkcs11/P11Signature.java Fri Oct 30 07:09:00 2020 +0000 6.3 @@ -245,10 +245,12 @@ 6.4 return; 6.5 } 6.6 initialized = false; 6.7 + 6.8 try { 6.9 if (session == null) { 6.10 return; 6.11 } 6.12 + 6.13 if (doCancel && token.explicitCancel) { 6.14 cancelOperation(); 6.15 } 6.16 @@ -259,59 +261,51 @@ 6.17 } 6.18 6.19 private void cancelOperation() { 6.20 - 6.21 token.ensureValid(); 6.22 - if (session.hasObjects() == false) { 6.23 - session = token.killSession(session); 6.24 - return; 6.25 - } else { 6.26 - // "cancel" operation by finishing it 6.27 - // XXX make sure all this always works correctly 6.28 + // cancel operation by finishing it; avoid killSession as some 6.29 + // hardware vendors may require re-login 6.30 + try { 6.31 if (mode == M_SIGN) { 6.32 - try { 6.33 - if (type == T_UPDATE) { 6.34 - token.p11.C_SignFinal(session.id(), 0); 6.35 - } else { 6.36 - byte[] digest; 6.37 - if (type == T_DIGEST) { 6.38 - digest = md.digest(); 6.39 - } else { // T_RAW 6.40 - digest = buffer; 6.41 - } 6.42 - token.p11.C_Sign(session.id(), digest); 6.43 + if (type == T_UPDATE) { 6.44 + token.p11.C_SignFinal(session.id(), 0); 6.45 + } else { 6.46 + byte[] digest; 6.47 + if (type == T_DIGEST) { 6.48 + digest = md.digest(); 6.49 + } else { // T_RAW 6.50 + digest = buffer; 6.51 } 6.52 - } catch (PKCS11Exception e) { 6.53 - throw new ProviderException("cancel failed", e); 6.54 + token.p11.C_Sign(session.id(), digest); 6.55 } 6.56 } else { // M_VERIFY 6.57 byte[] signature; 6.58 - try { 6.59 - if (keyAlgorithm.equals("DSA")) { 6.60 - signature = new byte[40]; 6.61 - } else { 6.62 - signature = new byte[(p11Key.length() + 7) >> 3]; 6.63 + if (keyAlgorithm.equals("DSA")) { 6.64 + signature = new byte[40]; 6.65 + } else { 6.66 + signature = new byte[(p11Key.length() + 7) >> 3]; 6.67 + } 6.68 + if (type == T_UPDATE) { 6.69 + token.p11.C_VerifyFinal(session.id(), signature); 6.70 + } else { 6.71 + byte[] digest; 6.72 + if (type == T_DIGEST) { 6.73 + digest = md.digest(); 6.74 + } else { // T_RAW 6.75 + digest = buffer; 6.76 } 6.77 - if (type == T_UPDATE) { 6.78 - token.p11.C_VerifyFinal(session.id(), signature); 6.79 - } else { 6.80 - byte[] digest; 6.81 - if (type == T_DIGEST) { 6.82 - digest = md.digest(); 6.83 - } else { // T_RAW 6.84 - digest = buffer; 6.85 - } 6.86 - token.p11.C_Verify(session.id(), digest, signature); 6.87 - } 6.88 - } catch (PKCS11Exception e) { 6.89 - long errorCode = e.getErrorCode(); 6.90 - if ((errorCode == CKR_SIGNATURE_INVALID) || 6.91 - (errorCode == CKR_SIGNATURE_LEN_RANGE)) { 6.92 - // expected since signature is incorrect 6.93 - return; 6.94 - } 6.95 - throw new ProviderException("cancel failed", e); 6.96 + token.p11.C_Verify(session.id(), digest, signature); 6.97 } 6.98 } 6.99 + } catch (PKCS11Exception e) { 6.100 + if (mode == M_VERIFY) { 6.101 + long errorCode = e.getErrorCode(); 6.102 + if ((errorCode == CKR_SIGNATURE_INVALID) || 6.103 + (errorCode == CKR_SIGNATURE_LEN_RANGE)) { 6.104 + // expected since signature is incorrect 6.105 + return; 6.106 + } 6.107 + } 6.108 + throw new ProviderException("cancel failed", e); 6.109 } 6.110 } 6.111