Webserver+3d print

Dependents:   Nucleo

cyclone_crypto/dh.c

Committer:
Sergunb
Date:
2017-02-04
Revision:
0:8918a71cdbe9

File content as of revision 0:8918a71cdbe9:

/**
 * @file dh.c
 * @brief Diffie-Hellman key exchange
 *
 * @section License
 *
 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneCrypto Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @section Description
 *
 * The Diffie-Hellman key agreement protocol allows two users to exchange a
 * secret key over an insecure medium without any prior secrets. Refer to
 * PKCS #3 (Diffie-Hellman Key-Agreement Standard)
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 1.7.6
 **/

//Switch to the appropriate trace level
#define TRACE_LEVEL CRYPTO_TRACE_LEVEL

//Dependencies
#include <stdlib.h>
#include "crypto.h"
#include "dh.h"
#include "debug.h"

//Check crypto library configuration
#if (DH_SUPPORT == ENABLED)


/**
 * @brief Initialize Diffie-Hellman context
 * @param[in] context Pointer to the Diffie-Hellman context
 **/

void dhInit(DhContext *context)
{
   //Initialize Diffie-Hellman parameters
   mpiInit(&context->params.p);
   mpiInit(&context->params.g);
   //Initialize private and public values
   mpiInit(&context->xa);
   mpiInit(&context->ya);
   mpiInit(&context->yb);
}


/**
 * @brief Release Diffie-Hellman context
 * @param[in] context Pointer to the Diffie-Hellman context
 **/

void dhFree(DhContext *context)
{
   //Release Diffie-Hellman parameters
   mpiFree(&context->params.p);
   mpiFree(&context->params.g);
   //Release private and public values
   mpiFree(&context->xa);
   mpiFree(&context->ya);
   mpiFree(&context->yb);
}


/**
 * @brief Diffie-Hellman key pair generation
 * @param[in] context Pointer to the Diffie-Hellman context
 * @param[in] prngAlgo PRNG algorithm
 * @param[in] prngContext Pointer to the PRNG context
 * @return Error code
 **/

error_t dhGenerateKeyPair(DhContext *context,
   const PrngAlgo *prngAlgo, void *prngContext)
{
   error_t error;
   uint_t k;

   //Debug message
   TRACE_DEBUG("Generating Diffie-Hellman key pair...\r\n");

   //Get the length in bits of the prime p
   k = mpiGetBitLength(&context->params.p);
   //Ensure the length is valid
   if(k == 0)
      return ERROR_INVALID_PARAMETER;

   //The private value shall be randomly generated
   error = mpiRand(&context->xa, k, prngAlgo, prngContext);
   //Any error to report?
   if(error)
      return error;

   //The private value shall be less than p
   if(mpiComp(&context->xa, &context->params.p) >= 0)
   {
      //Shift value to the right
      error = mpiShiftRight(&context->xa, 1);
      //Any error to report?
      if(error)
         return error;
   }

   //Debug message
   TRACE_DEBUG("  Private value:\r\n");
   TRACE_DEBUG_MPI("    ", &context->xa);

   //Calculate the corresponding public value (ya = g ^ xa mod p)
   error = mpiExpMod(&context->ya, &context->params.g, &context->xa, &context->params.p);
   //Any error to report?
   if(error)
      return error;

   //Debug message
   TRACE_DEBUG("  Public value:\r\n");
   TRACE_DEBUG_MPI("    ", &context->ya);

   //Check public value
   error = dhCheckPublicKey(&context->params, &context->ya);
   //Weak public value?
   if(error)
      return error;

   //Public value successfully generated
   return NO_ERROR;
}


/**
 * @brief Check Diffie-Hellman public value
 * @param[in] params Pointer to the Diffie-Hellman parameters
 * @param[in] publicKey Public value to be checked
 * @return Error code
 **/

error_t dhCheckPublicKey(DhParameters *params, const Mpi *publicKey)
{
   error_t error;
   Mpi a;

   //Initialize multiple precision integer
   mpiInit(&a);
   //Precompute p - 1
   error = mpiSubInt(&a, &params->p, 1);

   //Check status
   if(!error)
   {
      //Reject weak public values 1 and p - 1
      if(mpiCompInt(publicKey, 1) <= 0)
         error = ERROR_ILLEGAL_PARAMETER;
      else if(mpiComp(publicKey, &a) >= 0)
         error = ERROR_ILLEGAL_PARAMETER;
   }

   //Free previously allocated resources
   mpiFree(&a);
   //Return status code
   return error;
}


/**
 * @brief Compute Diffie-Hellman shared secret
 * @param[in] context Pointer to the Diffie-Hellman context
 * @param[out] output Buffer where to store the shared secret
 * @param[in] outputSize Size of the buffer in bytes
 * @param[out] outputLength Length of the resulting shared secret
 * @return Error code
 **/

error_t dhComputeSharedSecret(DhContext *context,
   uint8_t *output, size_t outputSize, size_t *outputLength)
{
   error_t error;
   size_t k;
   Mpi z;

   //Debug message
   TRACE_DEBUG("Computing Diffie-Hellman shared secret...\r\n");

   //Get the length in octets of the prime modulus
   k = mpiGetByteLength(&context->params.p);

   //Make sure that the output buffer is large enough
   if(outputSize < k)
      return ERROR_INVALID_LENGTH;

   //The multiple precision integer must be initialized before it can be used
   mpiInit(&z);

   //Start of exception handling block
   do
   {
      //Calculate the shared secret key (k = yb ^ xa mod p)
      error = mpiExpMod(&z, &context->yb, &context->xa, &context->params.p);
      //Any error to report?
      if(error)
         break;

      //Convert the resulting integer to an octet string
      error = mpiWriteRaw(&z, output, k);
      //Conversion failed?
      if(error)
         break;

      //Length of the resulting shared secret
      *outputLength = k;

      //Debug message
      TRACE_DEBUG("  Shared secret (%" PRIuSIZE " bytes):\r\n", *outputLength);
      TRACE_DEBUG_ARRAY("    ", output, *outputLength);

      //End of exception handling block
   } while(0);

   //Release previously allocated resources
   mpiFree(&z);
   //Return status code
   return error;
}

#endif