Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dh.c
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, ¶ms->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
Generated on Tue Jul 12 2022 17:10:12 by
