Home | History | Annotate | Download | only in securegcm
      1 /* Copyright 2018 Google LLC
      2  *
      3  * Licensed under the Apache License, Version 2.0 (the "License");
      4  * you may not use this file except in compliance with the License.
      5  * You may obtain a copy of the License at
      6  *
      7  *     https://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software
     10  * distributed under the License is distributed on an "AS IS" BASIS,
     11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12  * See the License for the specific language governing permissions and
     13  * limitations under the License.
     14  */
     15 package com.google.security.cryptauth.lib.securegcm;
     16 
     17 /**
     18  * Describes a cryptographic handshake with arbitrary number of round trips.  Some handshake
     19  * messages may also send a payload.
     20  *
     21  * <p>Generic usage for handshake Initiator:
     22  * {@code
     23  *   // Handshake Initiator
     24  *   D2DHandshakeContext handshake = <specific handshake>.forInitiator();
     25  *   while (!handshake.isHandshakeComplete()) {
     26  *     try {
     27  *       // Get the next handshake message to send
     28  *       byte[] initiatorMessage = handshake.getNextHandshakeMessage();
     29  *
     30  *       // Send the message out and get the response
     31  *       socket.send(initiatorMessage);
     32  *       byte[] responderMessage = socket.read();
     33  *
     34  *       // Handle the response and obtain the optional payload
     35  *       byte[] payload = handshake.parseHandshakeMessage(responderMessage);
     36  *
     37  *       // Handle the payload if one was sent
     38  *       if (payload.length > 0) {
     39  *         handlePayload(payload);
     40  *       }
     41  *     } catch (HandshakeException e) {
     42  *       // Handshake has failed, bail
     43  *       Log("Handshake failed!", e);
     44  *       return;
     45  *     }
     46  *   }
     47  *
     48  *   ConnectionContext connectionContext;
     49  *   try {
     50  *     // Upgrade handshake context to a full connection context
     51  *     connectionContext = handshake.toConnectionContext();
     52  *   } catch (HandshakeException e) {
     53  *     Log("Cannot convert handshake to connection context", e);
     54  *   }
     55  * }
     56  *
     57  * <p>Generic usage for handshake Responder:
     58  * {@code
     59  *   // Handshake Responder
     60  *   D2DHandshakeContext handshake = <specific handshake>.forResponder();
     61  *
     62  *   while (!handshake.isHandshakeComplete()) {
     63  *     try {
     64  *       // Get the message from the initiator
     65  *       byte[] initiatorMessage = socket.read();
     66  *
     67  *       // Handle the message and get the payload if it exists
     68  *       byte[] payload = handshake.parseHandshakeMessage(initiatorMessage);
     69  *
     70  *       // Handle the payload if one was sent
     71  *       if (payload.length > 0) {
     72  *         handlePayload(payload);
     73  *       }
     74  *
     75  *       // Make sure that wasn't the last message
     76  *       if (handshake.isHandshakeComplete()) {
     77  *         break;
     78  *       }
     79  *
     80  *       // Get next message to send and send it
     81  *       byte[] responderMessage = handshake.getNextHandshakeMessage();
     82  *       socket.send(responderMessage);
     83  *     } catch (HandshakeException e) {
     84  *       // Handshake has failed, bail
     85  *       Log("Handshake failed!", e);
     86  *       return;
     87  *     }
     88  *   }
     89  *
     90  *   ConnectionContext connectionContext;
     91  *   try {
     92  *     // Upgrade handshake context to a full connection context
     93  *     connectionContext = handshake.toConnectionContext();
     94  *   } catch (HandshakeException e) {
     95  *     Log("Cannot convert handshake to connection context", e);
     96  *   }
     97  * }
     98  */
     99 public interface D2DHandshakeContext {
    100 
    101   /**
    102    * Tells the caller whether the handshake has completed or not. If the handshake is complete, the
    103    * caller may call {@link #toConnectionContext()} to obtain a connection context.
    104    *
    105    * @return true if the handshake is complete, false otherwise
    106    */
    107   boolean isHandshakeComplete();
    108 
    109   /**
    110    * Constructs the next message that should be sent in the handshake.
    111    *
    112    * @return the next message
    113    * @throws HandshakeException if the handshake is over or if the next handshake message can't be
    114    *     obtained (e.g., there is an internal error)
    115    */
    116   byte[] getNextHandshakeMessage() throws HandshakeException;
    117 
    118   /**
    119    * Tells the caller whether the next handshake message may carry a payload. If true, caller may
    120    * call {@link #getNextHandshakeMessage(byte[])} instead of the regular
    121    * {@link #getNextHandshakeMessage()}. If false, calling {@link #getNextHandshakeMessage(byte[])}
    122    * will result in a {@link HandshakeException}.
    123    *
    124    * @return true if the next handshake message can carry a payload, false otherwise
    125    */
    126   boolean canSendPayloadInHandshakeMessage();
    127 
    128   /**
    129    * Constructs the next message that should be sent in the handshake along with a payload. Caller
    130    * should verify that this method can be called by calling
    131    * {@link #canSendPayloadInHandshakeMessage()}.
    132    *
    133    * @param payload the payload to include in the handshake message
    134    * @return the next message
    135    * @throws HandshakeException if the handshake is over or if the next handshake message can't be
    136    *     obtained (e.g., there is an internal error) or if the payload may not be included in this
    137    *     message
    138    */
    139   byte[] getNextHandshakeMessage(byte[] payload) throws HandshakeException;
    140 
    141   /**
    142    * Parses a handshake message and returns the included payload (if any).
    143    *
    144    * @param handshakeMessage message received in the handshake
    145    * @return payload or empty byte[] if no payload was in the handshake message
    146    * @throws HandshakeException if an error occurs in parsing the handshake message
    147    */
    148   byte[] parseHandshakeMessage(byte[] handshakeMessage) throws HandshakeException;
    149 
    150   /**
    151    * Creates a full {@link D2DConnectionContext}. May only be called if
    152    * {@link #isHandshakeComplete()} returns true.
    153    *
    154    * @return a full {@link D2DConnectionContext}
    155    * @throws HandshakeException if a connection context cannot be created
    156    */
    157   D2DConnectionContext toConnectionContext() throws HandshakeException;
    158 }
    159