Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ecdh.c Source File

ecdh.c

Go to the documentation of this file.
00001 /**
00002  * @file ecdh.c
00003  * @brief ECDH (Elliptic Curve 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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <stdlib.h>
00034 #include "crypto.h"
00035 #include "ecdh.h"
00036 #include "debug.h"
00037 
00038 //Check crypto library configuration
00039 #if (ECDH_SUPPORT == ENABLED)
00040 
00041 
00042 /**
00043  * @brief Initialize ECDH context
00044  * @param[in] context Pointer to the ECDH context
00045  **/
00046 
00047 void ecdhInit(EcdhContext *context)
00048 {
00049    //Initialize EC domain parameters
00050    ecInitDomainParameters(&context->params);
00051    //Initialize private and public keys
00052    mpiInit(&context->da);
00053    ecInit(&context->qa);
00054    ecInit(&context->qb);
00055 }
00056 
00057 
00058 /**
00059  * @brief Release ECDH context
00060  * @param[in] context Pointer to the ECDH context
00061  **/
00062 
00063 void ecdhFree(EcdhContext *context)
00064 {
00065    //Release EC domain parameters
00066    ecFreeDomainParameters(&context->params);
00067    //Release private and public keys
00068    mpiFree(&context->da);
00069    ecFree(&context->qa);
00070    ecFree(&context->qb);
00071 }
00072 
00073 
00074 /**
00075  * @brief ECDH key pair generation
00076  * @param[in] context Pointer to the ECDH context
00077  * @param[in] prngAlgo PRNG algorithm
00078  * @param[in] prngContext Pointer to the PRNG context
00079  * @return Error code
00080  **/
00081 
00082 error_t ecdhGenerateKeyPair(EcdhContext *context,
00083    const PrngAlgo *prngAlgo, void *prngContext)
00084 {
00085    error_t error;
00086    uint_t n;
00087 
00088    //Debug message
00089    TRACE_DEBUG("Generating ECDH key pair...\r\n");
00090 
00091    //Let N be the bit length of q
00092    n = mpiGetBitLength(&context->params.q);
00093 
00094    //Generated a pseudorandom number
00095    MPI_CHECK(mpiRand(&context->da, n, prngAlgo, prngContext));
00096 
00097    //Make sure that 0 < da < q
00098    if(mpiComp(&context->da, &context->params.q) >= 0)
00099       mpiShiftRight(&context->da, 1);
00100 
00101    //Debug message
00102    TRACE_DEBUG("  Private key:\r\n");
00103    TRACE_DEBUG_MPI("    ", &context->da);
00104 
00105    //Compute Qa = da.G
00106    EC_CHECK(ecMult(&context->params, &context->qa, &context->da, &context->params.g));
00107    EC_CHECK(ecAffinify(&context->params, &context->qa, &context->qa));
00108 
00109    //Debug message
00110    TRACE_DEBUG("  Public key X:\r\n");
00111    TRACE_DEBUG_MPI("    ", &context->qa.x);
00112    TRACE_DEBUG("  Public key Y:\r\n");
00113    TRACE_DEBUG_MPI("    ", &context->qa.y);
00114 
00115 end:
00116    //Return status code
00117    return error;
00118 }
00119 
00120 
00121 /**
00122  * @brief Check ECDH public key
00123  * @param[in] params EC domain parameters
00124  * @param[in] publicKey Public key to be checked
00125  * @return Error code
00126  **/
00127 
00128 error_t ecdhCheckPublicKey(const EcDomainParameters *params, EcPoint *publicKey)
00129 {
00130    bool_t valid;
00131 
00132    //Verify that 0 <= Qx < p
00133    if(mpiCompInt(&publicKey->x, 0) < 0)
00134       return ERROR_ILLEGAL_PARAMETER;
00135    else if(mpiComp(&publicKey->x, &params->p) >= 0)
00136       return ERROR_ILLEGAL_PARAMETER;
00137 
00138    //Verify that 0 <= Qy < p
00139    if(mpiCompInt(&publicKey->y, 0) < 0)
00140       return ERROR_ILLEGAL_PARAMETER;
00141    else if(mpiComp(&publicKey->y, &params->p) >= 0)
00142       return ERROR_ILLEGAL_PARAMETER;
00143 
00144    //Check whether the point is on the curve
00145    valid = ecIsPointAffine(params, publicKey);
00146 
00147    //Return status code
00148    return valid ? NO_ERROR : ERROR_FAILURE;
00149 }
00150 
00151 
00152 /**
00153  * @brief Compute ECDH shared secret
00154  * @param[in] context Pointer to the ECDH context
00155  * @param[out] output Buffer where to store the shared secret
00156  * @param[in] outputSize Size of the buffer in bytes
00157  * @param[out] outputLength Length of the resulting shared secret
00158  * @return Error code
00159  **/
00160 
00161 error_t ecdhComputeSharedSecret(EcdhContext *context,
00162    uint8_t *output, size_t outputSize, size_t *outputLength)
00163 {
00164    error_t error;
00165    size_t k;
00166    EcPoint z;
00167 
00168    //Debug message
00169    TRACE_DEBUG("Computing Diffie-Hellman shared secret...\r\n");
00170 
00171    //Get the length in octets of the prime modulus
00172    k = mpiGetByteLength(&context->params.p);
00173 
00174    //Make sure that the output buffer is large enough
00175    if(outputSize < k)
00176       return ERROR_INVALID_LENGTH;
00177 
00178    //Initialize EC points
00179    ecInit(&z);
00180 
00181    //Compute Z = da.Qb
00182    EC_CHECK(ecProjectify(&context->params, &context->qb, &context->qb));
00183    EC_CHECK(ecMult(&context->params, &z, &context->da, &context->qb));
00184    EC_CHECK(ecAffinify(&context->params, &z, &z));
00185 
00186    //Convert the x-coordinate of Z to an octet string
00187    MPI_CHECK(mpiWriteRaw(&z.x, output, k));
00188 
00189    //Length of the resulting shared secret
00190    *outputLength = k;
00191 
00192    //Debug message
00193    TRACE_DEBUG("  Shared secret (%" PRIuSIZE " bytes):\r\n", *outputLength);
00194    TRACE_DEBUG_ARRAY("    ", output, *outputLength);
00195 
00196 end:
00197    //Release EC points
00198    ecFree(&z);
00199 
00200    //Return status code
00201    return error;
00202 }
00203 
00204 #endif
00205