jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java
changeset 3492 e549cea58864
child 3863 8e0f58b1c072
equal deleted inserted replaced
3480:c197e38bf15a 3492:e549cea58864
       
     1 /*
       
     2  * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.security.ec;
       
    27 
       
    28 import java.security.*;
       
    29 import java.security.interfaces.*;
       
    30 import java.security.spec.*;
       
    31 
       
    32 import javax.crypto.*;
       
    33 import javax.crypto.spec.*;
       
    34 
       
    35 /**
       
    36  * KeyAgreement implementation for ECDH.
       
    37  *
       
    38  * @since   1.7
       
    39  */
       
    40 public final class ECDHKeyAgreement extends KeyAgreementSpi {
       
    41 
       
    42     // flag indicating whether the native ECC implementation is present
       
    43     private static boolean implementationPresent = true;
       
    44     static {
       
    45         try {
       
    46             AccessController.doPrivileged(new PrivilegedAction<Void>() {
       
    47                 public Void run() {
       
    48                     System.loadLibrary("sunecc");
       
    49                     return null;
       
    50                 }
       
    51             });
       
    52         } catch (UnsatisfiedLinkError e) {
       
    53             implementationPresent = false;
       
    54         }
       
    55     }
       
    56 
       
    57     // private key, if initialized
       
    58     private ECPrivateKey privateKey;
       
    59 
       
    60     // encoded public point, non-null between doPhase() & generateSecret() only
       
    61     private byte[] publicValue;
       
    62 
       
    63     // length of the secret to be derived
       
    64     private int secretLen;
       
    65 
       
    66     /**
       
    67      * Constructs a new ECDHKeyAgreement.
       
    68      *
       
    69      * @exception ProviderException if the native ECC library is unavailable.
       
    70      */
       
    71     public ECDHKeyAgreement() {
       
    72         if (!implementationPresent) {
       
    73             throw new ProviderException("ECDH implementation is not available");
       
    74         }
       
    75     }
       
    76 
       
    77     // see JCE spec
       
    78     protected void engineInit(Key key, SecureRandom random)
       
    79             throws InvalidKeyException {
       
    80         if (!(key instanceof PrivateKey)) {
       
    81             throw new InvalidKeyException
       
    82                         ("Key must be instance of PrivateKey");
       
    83         }
       
    84         privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
       
    85         publicValue = null;
       
    86     }
       
    87 
       
    88     // see JCE spec
       
    89     protected void engineInit(Key key, AlgorithmParameterSpec params,
       
    90             SecureRandom random) throws InvalidKeyException,
       
    91             InvalidAlgorithmParameterException {
       
    92         if (params != null) {
       
    93             throw new InvalidAlgorithmParameterException
       
    94                         ("Parameters not supported");
       
    95         }
       
    96         engineInit(key, random);
       
    97     }
       
    98 
       
    99     // see JCE spec
       
   100     protected Key engineDoPhase(Key key, boolean lastPhase)
       
   101             throws InvalidKeyException, IllegalStateException {
       
   102         if (privateKey == null) {
       
   103             throw new IllegalStateException("Not initialized");
       
   104         }
       
   105         if (publicValue != null) {
       
   106             throw new IllegalStateException("Phase already executed");
       
   107         }
       
   108         if (!lastPhase) {
       
   109             throw new IllegalStateException
       
   110                 ("Only two party agreement supported, lastPhase must be true");
       
   111         }
       
   112         if (!(key instanceof ECPublicKey)) {
       
   113             throw new InvalidKeyException
       
   114                 ("Key must be a PublicKey with algorithm EC");
       
   115         }
       
   116 
       
   117         ECPublicKey ecKey = (ECPublicKey)key;
       
   118         ECParameterSpec params = ecKey.getParams();
       
   119 
       
   120         if (ecKey instanceof ECPublicKeyImpl) {
       
   121             publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
       
   122         } else { // instanceof ECPublicKey
       
   123             publicValue =
       
   124                 ECParameters.encodePoint(ecKey.getW(), params.getCurve());
       
   125         }
       
   126         int keyLenBits = params.getCurve().getField().getFieldSize();
       
   127         secretLen = (keyLenBits + 7) >> 3;
       
   128 
       
   129         return null;
       
   130     }
       
   131 
       
   132     // see JCE spec
       
   133     protected byte[] engineGenerateSecret() throws IllegalStateException {
       
   134         if ((privateKey == null) || (publicValue == null)) {
       
   135             throw new IllegalStateException("Not initialized correctly");
       
   136         }
       
   137 
       
   138         byte[] s = privateKey.getS().toByteArray();
       
   139         byte[] encodedParams =
       
   140             ECParameters.encodeParameters(privateKey.getParams()); // DER OID
       
   141 
       
   142         try {
       
   143 
       
   144             return deriveKey(s, publicValue, encodedParams);
       
   145 
       
   146         } catch (GeneralSecurityException e) {
       
   147             throw new ProviderException("Could not derive key", e);
       
   148         }
       
   149 
       
   150     }
       
   151 
       
   152     // see JCE spec
       
   153     protected int engineGenerateSecret(byte[] sharedSecret, int
       
   154             offset) throws IllegalStateException, ShortBufferException {
       
   155         if (offset + secretLen > sharedSecret.length) {
       
   156             throw new ShortBufferException("Need " + secretLen
       
   157                 + " bytes, only " + (sharedSecret.length - offset) + " available");
       
   158         }
       
   159         byte[] secret = engineGenerateSecret();
       
   160         System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
       
   161         return secret.length;
       
   162     }
       
   163 
       
   164     // see JCE spec
       
   165     protected SecretKey engineGenerateSecret(String algorithm)
       
   166             throws IllegalStateException, NoSuchAlgorithmException,
       
   167             InvalidKeyException {
       
   168         if (algorithm == null) {
       
   169             throw new NoSuchAlgorithmException("Algorithm must not be null");
       
   170         }
       
   171         if (!(algorithm.equals("TlsPremasterSecret"))) {
       
   172             throw new NoSuchAlgorithmException
       
   173                 ("Only supported for algorithm TlsPremasterSecret");
       
   174         }
       
   175         return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
       
   176     }
       
   177 
       
   178     /**
       
   179      * Generates a secret key using the public and private keys.
       
   180      *
       
   181      * @param s the private key's S value.
       
   182      * @param w the public key's W point (in uncompressed form).
       
   183      * @param encodedParams the curve's DER encoded object identifier.
       
   184      *
       
   185      * @return byte[] the secret key.
       
   186      */
       
   187     private static native byte[] deriveKey(byte[] s, byte[] w,
       
   188         byte[] encodedParams) throws GeneralSecurityException;
       
   189 }