1545N/A/*
2362N/A * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
1545N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1545N/A *
1545N/A * This code is free software; you can redistribute it and/or modify it
1545N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
1545N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
1545N/A *
1545N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1545N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1545N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1545N/A * version 2 for more details (a copy is included in the LICENSE file that
1545N/A * accompanied this code).
1545N/A *
1545N/A * You should have received a copy of the GNU General Public License version
1545N/A * 2 along with this work; if not, write to the Free Software Foundation,
1545N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1545N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
1545N/A */
1545N/A
1545N/Apackage sun.security.ec;
1545N/A
1545N/Aimport java.security.*;
1545N/Aimport java.security.interfaces.*;
1545N/Aimport java.security.spec.*;
1545N/A
1545N/Aimport javax.crypto.*;
1545N/Aimport javax.crypto.spec.*;
1545N/A
1545N/A/**
1545N/A * KeyAgreement implementation for ECDH.
1545N/A *
1545N/A * @since 1.7
1545N/A */
1545N/Apublic final class ECDHKeyAgreement extends KeyAgreementSpi {
1545N/A
1545N/A // private key, if initialized
1545N/A private ECPrivateKey privateKey;
1545N/A
1545N/A // encoded public point, non-null between doPhase() & generateSecret() only
1545N/A private byte[] publicValue;
1545N/A
1545N/A // length of the secret to be derived
1545N/A private int secretLen;
1545N/A
1545N/A /**
1545N/A * Constructs a new ECDHKeyAgreement.
1545N/A */
1545N/A public ECDHKeyAgreement() {
1545N/A }
1545N/A
1545N/A // see JCE spec
1674N/A @Override
1545N/A protected void engineInit(Key key, SecureRandom random)
1545N/A throws InvalidKeyException {
1545N/A if (!(key instanceof PrivateKey)) {
1545N/A throw new InvalidKeyException
1545N/A ("Key must be instance of PrivateKey");
1545N/A }
1545N/A privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
1545N/A publicValue = null;
1545N/A }
1545N/A
1545N/A // see JCE spec
1674N/A @Override
1545N/A protected void engineInit(Key key, AlgorithmParameterSpec params,
1545N/A SecureRandom random) throws InvalidKeyException,
1545N/A InvalidAlgorithmParameterException {
1545N/A if (params != null) {
1545N/A throw new InvalidAlgorithmParameterException
1545N/A ("Parameters not supported");
1545N/A }
1545N/A engineInit(key, random);
1545N/A }
1545N/A
1545N/A // see JCE spec
1674N/A @Override
1545N/A protected Key engineDoPhase(Key key, boolean lastPhase)
1545N/A throws InvalidKeyException, IllegalStateException {
1545N/A if (privateKey == null) {
1545N/A throw new IllegalStateException("Not initialized");
1545N/A }
1545N/A if (publicValue != null) {
1545N/A throw new IllegalStateException("Phase already executed");
1545N/A }
1545N/A if (!lastPhase) {
1545N/A throw new IllegalStateException
1545N/A ("Only two party agreement supported, lastPhase must be true");
1545N/A }
1545N/A if (!(key instanceof ECPublicKey)) {
1545N/A throw new InvalidKeyException
1545N/A ("Key must be a PublicKey with algorithm EC");
1545N/A }
1545N/A
1545N/A ECPublicKey ecKey = (ECPublicKey)key;
1545N/A ECParameterSpec params = ecKey.getParams();
1545N/A
1545N/A if (ecKey instanceof ECPublicKeyImpl) {
1545N/A publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
1545N/A } else { // instanceof ECPublicKey
1545N/A publicValue =
1545N/A ECParameters.encodePoint(ecKey.getW(), params.getCurve());
1545N/A }
1545N/A int keyLenBits = params.getCurve().getField().getFieldSize();
1545N/A secretLen = (keyLenBits + 7) >> 3;
1545N/A
1545N/A return null;
1545N/A }
1545N/A
1545N/A // see JCE spec
1674N/A @Override
1545N/A protected byte[] engineGenerateSecret() throws IllegalStateException {
1545N/A if ((privateKey == null) || (publicValue == null)) {
1545N/A throw new IllegalStateException("Not initialized correctly");
1545N/A }
1545N/A
1545N/A byte[] s = privateKey.getS().toByteArray();
1545N/A byte[] encodedParams =
1545N/A ECParameters.encodeParameters(privateKey.getParams()); // DER OID
1545N/A
1545N/A try {
1545N/A
1545N/A return deriveKey(s, publicValue, encodedParams);
1545N/A
1545N/A } catch (GeneralSecurityException e) {
1545N/A throw new ProviderException("Could not derive key", e);
1545N/A }
1545N/A
1545N/A }
1545N/A
1545N/A // see JCE spec
1674N/A @Override
1545N/A protected int engineGenerateSecret(byte[] sharedSecret, int
1545N/A offset) throws IllegalStateException, ShortBufferException {
1545N/A if (offset + secretLen > sharedSecret.length) {
1545N/A throw new ShortBufferException("Need " + secretLen
1545N/A + " bytes, only " + (sharedSecret.length - offset) + " available");
1545N/A }
1545N/A byte[] secret = engineGenerateSecret();
1545N/A System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
1545N/A return secret.length;
1545N/A }
1545N/A
1545N/A // see JCE spec
1674N/A @Override
1545N/A protected SecretKey engineGenerateSecret(String algorithm)
1545N/A throws IllegalStateException, NoSuchAlgorithmException,
1545N/A InvalidKeyException {
1545N/A if (algorithm == null) {
1545N/A throw new NoSuchAlgorithmException("Algorithm must not be null");
1545N/A }
1545N/A if (!(algorithm.equals("TlsPremasterSecret"))) {
1545N/A throw new NoSuchAlgorithmException
1545N/A ("Only supported for algorithm TlsPremasterSecret");
1545N/A }
1545N/A return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
1545N/A }
1545N/A
1545N/A /**
1545N/A * Generates a secret key using the public and private keys.
1545N/A *
1545N/A * @param s the private key's S value.
1545N/A * @param w the public key's W point (in uncompressed form).
1545N/A * @param encodedParams the curve's DER encoded object identifier.
1545N/A *
1545N/A * @return byte[] the secret key.
1545N/A */
1545N/A private static native byte[] deriveKey(byte[] s, byte[] w,
1545N/A byte[] encodedParams) throws GeneralSecurityException;
1545N/A}