Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dh.c Source File

dh.c

Go to the documentation of this file.
00001 /**
00002  * @file dh.c
00003  * @brief Diffie-Hellman key exchange
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneCrypto Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @section Description
00026  *
00027  * The Diffie-Hellman key agreement protocol allows two users to exchange a
00028  * secret key over an insecure medium without any prior secrets. Refer to
00029  * PKCS #3 (Diffie-Hellman Key-Agreement Standard)
00030  *
00031  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00032  * @version 1.7.6
00033  **/
00034 
00035 //Switch to the appropriate trace level
00036 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00037 
00038 //Dependencies
00039 #include <stdlib.h>
00040 #include "crypto.h"
00041 #include "dh.h"
00042 #include "debug.h"
00043 
00044 //Check crypto library configuration
00045 #if (DH_SUPPORT == ENABLED)
00046 
00047 
00048 /**
00049  * @brief Initialize Diffie-Hellman context
00050  * @param[in] context Pointer to the Diffie-Hellman context
00051  **/
00052 
00053 void dhInit(DhContext *context)
00054 {
00055    //Initialize Diffie-Hellman parameters
00056    mpiInit(&context->params.p);
00057    mpiInit(&context->params.g);
00058    //Initialize private and public values
00059    mpiInit(&context->xa);
00060    mpiInit(&context->ya);
00061    mpiInit(&context->yb);
00062 }
00063 
00064 
00065 /**
00066  * @brief Release Diffie-Hellman context
00067  * @param[in] context Pointer to the Diffie-Hellman context
00068  **/
00069 
00070 void dhFree(DhContext *context)
00071 {
00072    //Release Diffie-Hellman parameters
00073    mpiFree(&context->params.p);
00074    mpiFree(&context->params.g);
00075    //Release private and public values
00076    mpiFree(&context->xa);
00077    mpiFree(&context->ya);
00078    mpiFree(&context->yb);
00079 }
00080 
00081 
00082 /**
00083  * @brief Diffie-Hellman key pair generation
00084  * @param[in] context Pointer to the Diffie-Hellman context
00085  * @param[in] prngAlgo PRNG algorithm
00086  * @param[in] prngContext Pointer to the PRNG context
00087  * @return Error code
00088  **/
00089 
00090 error_t dhGenerateKeyPair(DhContext *context,
00091    const PrngAlgo *prngAlgo, void *prngContext)
00092 {
00093    error_t error;
00094    uint_t k;
00095 
00096    //Debug message
00097    TRACE_DEBUG("Generating Diffie-Hellman key pair...\r\n");
00098 
00099    //Get the length in bits of the prime p
00100    k = mpiGetBitLength(&context->params.p);
00101    //Ensure the length is valid
00102    if(k == 0)
00103       return ERROR_INVALID_PARAMETER;
00104 
00105    //The private value shall be randomly generated
00106    error = mpiRand(&context->xa, k, prngAlgo, prngContext);
00107    //Any error to report?
00108    if(error)
00109       return error;
00110 
00111    //The private value shall be less than p
00112    if(mpiComp(&context->xa, &context->params.p) >= 0)
00113    {
00114       //Shift value to the right
00115       error = mpiShiftRight(&context->xa, 1);
00116       //Any error to report?
00117       if(error)
00118          return error;
00119    }
00120 
00121    //Debug message
00122    TRACE_DEBUG("  Private value:\r\n");
00123    TRACE_DEBUG_MPI("    ", &context->xa);
00124 
00125    //Calculate the corresponding public value (ya = g ^ xa mod p)
00126    error = mpiExpMod(&context->ya, &context->params.g, &context->xa, &context->params.p);
00127    //Any error to report?
00128    if(error)
00129       return error;
00130 
00131    //Debug message
00132    TRACE_DEBUG("  Public value:\r\n");
00133    TRACE_DEBUG_MPI("    ", &context->ya);
00134 
00135    //Check public value
00136    error = dhCheckPublicKey(&context->params, &context->ya);
00137    //Weak public value?
00138    if(error)
00139       return error;
00140 
00141    //Public value successfully generated
00142    return NO_ERROR;
00143 }
00144 
00145 
00146 /**
00147  * @brief Check Diffie-Hellman public value
00148  * @param[in] params Pointer to the Diffie-Hellman parameters
00149  * @param[in] publicKey Public value to be checked
00150  * @return Error code
00151  **/
00152 
00153 error_t dhCheckPublicKey(DhParameters *params, const Mpi *publicKey)
00154 {
00155    error_t error;
00156    Mpi a;
00157 
00158    //Initialize multiple precision integer
00159    mpiInit(&a);
00160    //Precompute p - 1
00161    error = mpiSubInt(&a, &params->p, 1);
00162 
00163    //Check status
00164    if(!error)
00165    {
00166       //Reject weak public values 1 and p - 1
00167       if(mpiCompInt(publicKey, 1) <= 0)
00168          error = ERROR_ILLEGAL_PARAMETER;
00169       else if(mpiComp(publicKey, &a) >= 0)
00170          error = ERROR_ILLEGAL_PARAMETER;
00171    }
00172 
00173    //Free previously allocated resources
00174    mpiFree(&a);
00175    //Return status code
00176    return error;
00177 }
00178 
00179 
00180 /**
00181  * @brief Compute Diffie-Hellman shared secret
00182  * @param[in] context Pointer to the Diffie-Hellman context
00183  * @param[out] output Buffer where to store the shared secret
00184  * @param[in] outputSize Size of the buffer in bytes
00185  * @param[out] outputLength Length of the resulting shared secret
00186  * @return Error code
00187  **/
00188 
00189 error_t dhComputeSharedSecret(DhContext *context,
00190    uint8_t *output, size_t outputSize, size_t *outputLength)
00191 {
00192    error_t error;
00193    size_t k;
00194    Mpi z;
00195 
00196    //Debug message
00197    TRACE_DEBUG("Computing Diffie-Hellman shared secret...\r\n");
00198 
00199    //Get the length in octets of the prime modulus
00200    k = mpiGetByteLength(&context->params.p);
00201 
00202    //Make sure that the output buffer is large enough
00203    if(outputSize < k)
00204       return ERROR_INVALID_LENGTH;
00205 
00206    //The multiple precision integer must be initialized before it can be used
00207    mpiInit(&z);
00208 
00209    //Start of exception handling block
00210    do
00211    {
00212       //Calculate the shared secret key (k = yb ^ xa mod p)
00213       error = mpiExpMod(&z, &context->yb, &context->xa, &context->params.p);
00214       //Any error to report?
00215       if(error)
00216          break;
00217 
00218       //Convert the resulting integer to an octet string
00219       error = mpiWriteRaw(&z, output, k);
00220       //Conversion failed?
00221       if(error)
00222          break;
00223 
00224       //Length of the resulting shared secret
00225       *outputLength = k;
00226 
00227       //Debug message
00228       TRACE_DEBUG("  Shared secret (%" PRIuSIZE " bytes):\r\n", *outputLength);
00229       TRACE_DEBUG_ARRAY("    ", output, *outputLength);
00230 
00231       //End of exception handling block
00232    } while(0);
00233 
00234    //Release previously allocated resources
00235    mpiFree(&z);
00236    //Return status code
00237    return error;
00238 }
00239 
00240 #endif
00241