| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package com.sun.crypto.provider;  | 
 | 
 | 
 | 
import sun.misc.ObjectInputFilter;  | 
 | 
import sun.misc.SharedSecrets;  | 
 | 
 | 
 | 
import java.io.*;  | 
 | 
import java.security.*;  | 
 | 
import javax.crypto.*;  | 
 | 
 | 
 | 
final class SealedObjectForKeyProtector extends SealedObject { | 
 | 
 | 
 | 
    static final long serialVersionUID = -3650226485480866989L;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final String KEY_SERIAL_FILTER = "jceks.key.serialFilter";  | 
 | 
 | 
 | 
    SealedObjectForKeyProtector(Serializable object, Cipher c)  | 
 | 
            throws IOException, IllegalBlockSizeException { | 
 | 
        super(object, c);  | 
 | 
    }  | 
 | 
 | 
 | 
    SealedObjectForKeyProtector(SealedObject so) { | 
 | 
        super(so);  | 
 | 
    }  | 
 | 
 | 
 | 
    AlgorithmParameters getParameters() { | 
 | 
        AlgorithmParameters params = null;  | 
 | 
        if (super.encodedParams != null) { | 
 | 
            try { | 
 | 
                params = AlgorithmParameters.getInstance("PBE", | 
 | 
                    SunJCE.getInstance());  | 
 | 
                params.init(super.encodedParams);  | 
 | 
            } catch (NoSuchAlgorithmException nsae) { | 
 | 
                throw new RuntimeException(  | 
 | 
                    "SunJCE provider is not configured properly");  | 
 | 
            } catch (IOException io) { | 
 | 
                throw new RuntimeException("Parameter failure: "+ | 
 | 
                    io.getMessage());  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return params;  | 
 | 
    }  | 
 | 
 | 
 | 
    final Key getKey(Cipher c, int maxLength)  | 
 | 
            throws IOException, ClassNotFoundException, IllegalBlockSizeException,  | 
 | 
            BadPaddingException { | 
 | 
 | 
 | 
        try (ObjectInputStream ois = SharedSecrets.getJavaxCryptoSealedObjectAccess()  | 
 | 
                .getExtObjectInputStream(this, c)) { | 
 | 
            AccessController.doPrivileged(  | 
 | 
                    (PrivilegedAction<Void>) () -> { | 
 | 
                        ObjectInputFilter.Config.setObjectInputFilter(ois,  | 
 | 
                                new DeserializationChecker(maxLength));  | 
 | 
                        return null;  | 
 | 
                    });  | 
 | 
            try { | 
 | 
                @SuppressWarnings("unchecked") | 
 | 
                Key t = (Key) ois.readObject();  | 
 | 
                return t;  | 
 | 
            } catch (InvalidClassException ice) { | 
 | 
                String msg = ice.getMessage();  | 
 | 
                if (msg.contains("REJECTED")) { | 
 | 
                    throw new IOException("Rejected by the" | 
 | 
                            + " jceks.key.serialFilter or jdk.serialFilter"  | 
 | 
                            + " property", ice);  | 
 | 
                } else { | 
 | 
                    throw ice;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static class DeserializationChecker implements ObjectInputFilter { | 
 | 
 | 
 | 
        private static final ObjectInputFilter OWN_FILTER;  | 
 | 
 | 
 | 
        static { | 
 | 
            String prop = AccessController.doPrivileged(  | 
 | 
                    (PrivilegedAction<String>) () -> { | 
 | 
                        String tmp = System.getProperty(KEY_SERIAL_FILTER);  | 
 | 
                        if (tmp != null) { | 
 | 
                            return tmp;  | 
 | 
                        } else { | 
 | 
                            return Security.getProperty(KEY_SERIAL_FILTER);  | 
 | 
                        }  | 
 | 
                    });  | 
 | 
            OWN_FILTER = prop == null  | 
 | 
                    ? null  | 
 | 
                    : ObjectInputFilter.Config.createFilter(prop);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        private final int maxLength;  | 
 | 
 | 
 | 
        private DeserializationChecker(int maxLength) { | 
 | 
            this.maxLength = maxLength;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public ObjectInputFilter.Status checkInput(  | 
 | 
                ObjectInputFilter.FilterInfo info) { | 
 | 
 | 
 | 
            if (info.arrayLength() > maxLength) { | 
 | 
                return Status.REJECTED;  | 
 | 
            }  | 
 | 
 | 
 | 
            if (info.serialClass() == Object.class) { | 
 | 
                return Status.UNDECIDED;  | 
 | 
            }  | 
 | 
 | 
 | 
            if (OWN_FILTER != null) { | 
 | 
                Status result = OWN_FILTER.checkInput(info);  | 
 | 
                if (result != Status.UNDECIDED) { | 
 | 
                    return result;  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            ObjectInputFilter defaultFilter =  | 
 | 
                    ObjectInputFilter.Config.getSerialFilter();  | 
 | 
            if (defaultFilter != null) { | 
 | 
                return defaultFilter.checkInput(info);  | 
 | 
            }  | 
 | 
 | 
 | 
            return Status.UNDECIDED;  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |