Webserver+3d print
Diff: cyclone_crypto/dh.c
- Revision:
- 0:8918a71cdbe9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cyclone_crypto/dh.c Sat Feb 04 18:15:49 2017 +0000 @@ -0,0 +1,241 @@ +/** + * @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, ¶ms->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 +