| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.ssl;  | 
 | 
 | 
 | 
import java.io.IOException;  | 
 | 
import java.nio.ByteBuffer;  | 
 | 
import java.security.GeneralSecurityException;  | 
 | 
import java.security.spec.AlgorithmParameterSpec;  | 
 | 
import javax.crypto.SecretKey;  | 
 | 
import javax.net.ssl.SSLHandshakeException;  | 
 | 
 | 
 | 
final class SSLBasicKeyDerivation implements SSLKeyDerivation { | 
 | 
    private final String hashAlg;  | 
 | 
    private final SecretKey secret;  | 
 | 
    private final byte[] hkdfInfo;  | 
 | 
 | 
 | 
    SSLBasicKeyDerivation(SecretKey secret, String hashAlg,  | 
 | 
            byte[] label, byte[] context, int length) { | 
 | 
        this.hashAlg = hashAlg.replace("-", ""); | 
 | 
        this.secret = secret;  | 
 | 
        this.hkdfInfo = createHkdfInfo(label, context, length);  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public SecretKey deriveKey(String algorithm,  | 
 | 
            AlgorithmParameterSpec keySpec) throws IOException { | 
 | 
        try { | 
 | 
            HKDF hkdf = new HKDF(hashAlg);  | 
 | 
            return hkdf.expand(secret, hkdfInfo,  | 
 | 
                    ((SecretSizeSpec)keySpec).length, algorithm);  | 
 | 
        } catch (GeneralSecurityException gse) { | 
 | 
            throw (SSLHandshakeException) new SSLHandshakeException(  | 
 | 
                "Could not generate secret").initCause(gse);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private static byte[] createHkdfInfo(  | 
 | 
            byte[] label, byte[] context, int length) { | 
 | 
        byte[] info = new byte[4 + label.length + context.length];  | 
 | 
        ByteBuffer m = ByteBuffer.wrap(info);  | 
 | 
        try { | 
 | 
            Record.putInt16(m, length);  | 
 | 
            Record.putBytes8(m, label);  | 
 | 
            Record.putBytes8(m, context);  | 
 | 
        } catch (IOException ioe) { | 
 | 
            // unlikely  | 
 | 
        }  | 
 | 
        return info;  | 
 | 
    }  | 
 | 
 | 
 | 
    static class SecretSizeSpec implements AlgorithmParameterSpec { | 
 | 
        final int length;  | 
 | 
 | 
 | 
        SecretSizeSpec(int length) { | 
 | 
            this.length = length;  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |