CryptDh.c revision 4fd606d1f5abe38e1f42c38de1d2e895166bd0f4
45e9809aff7304721fddb95654901b32195c9c7avboxsync/** @file
45e9809aff7304721fddb95654901b32195c9c7avboxsync Diffie-Hellman Wrapper Implementation over OpenSSL.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsyncCopyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
45e9809aff7304721fddb95654901b32195c9c7avboxsyncThis program and the accompanying materials
45e9809aff7304721fddb95654901b32195c9c7avboxsyncare licensed and made available under the terms and conditions of the BSD License
45e9809aff7304721fddb95654901b32195c9c7avboxsyncwhich accompanies this distribution. The full text of the license may be found at
45e9809aff7304721fddb95654901b32195c9c7avboxsynchttp://opensource.org/licenses/bsd-license.php
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
45e9809aff7304721fddb95654901b32195c9c7avboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync**/
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync#include "InternalCryptLib.h"
45e9809aff7304721fddb95654901b32195c9c7avboxsync#include <openssl/dh.h>
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync/**
45e9809aff7304721fddb95654901b32195c9c7avboxsync Allocates and Initializes one Diffie-Hellman Context for subsequent use.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @return Pointer to the Diffie-Hellman Context that has been initialized.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If the allocations fails, DhNew() returns NULL.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync**/
45e9809aff7304721fddb95654901b32195c9c7avboxsyncVOID *
45e9809aff7304721fddb95654901b32195c9c7avboxsyncEFIAPI
45e9809aff7304721fddb95654901b32195c9c7avboxsyncDhNew (
45e9809aff7304721fddb95654901b32195c9c7avboxsync VOID
45e9809aff7304721fddb95654901b32195c9c7avboxsync )
45e9809aff7304721fddb95654901b32195c9c7avboxsync{
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync // Allocates & Initializes DH Context by OpenSSL DH_new()
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync return (VOID *)DH_new ();
45e9809aff7304721fddb95654901b32195c9c7avboxsync}
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync/**
45e9809aff7304721fddb95654901b32195c9c7avboxsync Release the specified DH context.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync If DhContext is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in] DhContext Pointer to the DH context to be released.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync**/
45e9809aff7304721fddb95654901b32195c9c7avboxsyncVOID
45e9809aff7304721fddb95654901b32195c9c7avboxsyncEFIAPI
45e9809aff7304721fddb95654901b32195c9c7avboxsyncDhFree (
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN VOID *DhContext
45e9809aff7304721fddb95654901b32195c9c7avboxsync )
45e9809aff7304721fddb95654901b32195c9c7avboxsync{
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync // Free OpenSSL DH Context
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync DH_free ((DH *)DhContext);
45e9809aff7304721fddb95654901b32195c9c7avboxsync}
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync/**
45e9809aff7304721fddb95654901b32195c9c7avboxsync Generates DH parameter.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync Given generator g, and length of prime number p in bits, this function generates p,
45e9809aff7304721fddb95654901b32195c9c7avboxsync and sets DH context according to value of g and p.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync Before this function can be invoked, pseudorandom number generator must be correctly
45e9809aff7304721fddb95654901b32195c9c7avboxsync initialized by RandomSeed().
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync If DhContext is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If Prime is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in, out] DhContext Pointer to the DH context.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in] Generator Value of generator.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in] PrimeLength Length in bits of prime to be generated.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[out] Prime Pointer to the buffer to receive the generated prime number.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval TRUE DH pamameter generation succeeded.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE Value of Generator is not supported.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE PRNG fails to generate random prime number with PrimeLength.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync**/
45e9809aff7304721fddb95654901b32195c9c7avboxsyncBOOLEAN
45e9809aff7304721fddb95654901b32195c9c7avboxsyncEFIAPI
45e9809aff7304721fddb95654901b32195c9c7avboxsyncDhGenerateParameter (
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN OUT VOID *DhContext,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN UINTN Generator,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN UINTN PrimeLength,
45e9809aff7304721fddb95654901b32195c9c7avboxsync OUT UINT8 *Prime
45e9809aff7304721fddb95654901b32195c9c7avboxsync )
45e9809aff7304721fddb95654901b32195c9c7avboxsync{
45e9809aff7304721fddb95654901b32195c9c7avboxsync BOOLEAN RetVal;
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync // Check input parameters.
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (DhContext == NULL || Prime == NULL) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync return FALSE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync return FALSE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync RetVal = (BOOLEAN) DH_generate_parameters_ex (DhContext, (UINT32) PrimeLength, (UINT32) Generator, NULL);
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (!RetVal) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync return FALSE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync BN_bn2bin (((DH *) DhContext)->p, Prime);
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync return TRUE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync}
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync/**
45e9809aff7304721fddb95654901b32195c9c7avboxsync Sets generator and prime parameters for DH.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync Given generator g, and prime number p, this function and sets DH
45e9809aff7304721fddb95654901b32195c9c7avboxsync context accordingly.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync If DhContext is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If Prime is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in, out] DhContext Pointer to the DH context.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in] Generator Value of generator.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in] PrimeLength Length in bits of prime to be generated.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in] Prime Pointer to the prime number.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval TRUE DH pamameter setting succeeded.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE Value of Generator is not supported.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE Value of Generator is not suitable for the Prime.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE Value of Prime is not a prime number.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE Value of Prime is not a safe prime number.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync**/
45e9809aff7304721fddb95654901b32195c9c7avboxsyncBOOLEAN
45e9809aff7304721fddb95654901b32195c9c7avboxsyncEFIAPI
45e9809aff7304721fddb95654901b32195c9c7avboxsyncDhSetParameter (
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN OUT VOID *DhContext,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN UINTN Generator,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN UINTN PrimeLength,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN CONST UINT8 *Prime
45e9809aff7304721fddb95654901b32195c9c7avboxsync )
45e9809aff7304721fddb95654901b32195c9c7avboxsync{
45e9809aff7304721fddb95654901b32195c9c7avboxsync DH *Dh;
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync // Check input parameters.
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (DhContext == NULL || Prime == NULL) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync return FALSE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync return FALSE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync Dh = (DH *) DhContext;
45e9809aff7304721fddb95654901b32195c9c7avboxsync Dh->p = BN_new();
45e9809aff7304721fddb95654901b32195c9c7avboxsync Dh->g = BN_new();
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync BN_bin2bn (Prime, (UINT32) (PrimeLength / 8), Dh->p);
45e9809aff7304721fddb95654901b32195c9c7avboxsync BN_set_word (Dh->g, (UINT32) Generator);
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync return TRUE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync}
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync/**
45e9809aff7304721fddb95654901b32195c9c7avboxsync Generates DH public key.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync This function generates random secret exponent, and computes the public key, which is
45e9809aff7304721fddb95654901b32195c9c7avboxsync returned via parameter PublicKey and PublicKeySize. DH context is updated accordingly.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If the PublicKey buffer is too small to hold the public key, FALSE is returned and
45e9809aff7304721fddb95654901b32195c9c7avboxsync PublicKeySize is set to the required buffer size to obtain the public key.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync If DhContext is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If PublicKeySize is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If PublicKeySize is large enough but PublicKey is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in, out] DhContext Pointer to the DH context.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[out] PublicKey Pointer to the buffer to receive generated public key.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in, out] PublicKeySize On input, the size of PublicKey buffer in bytes.
45e9809aff7304721fddb95654901b32195c9c7avboxsync On output, the size of data returned in PublicKey buffer in bytes.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval TRUE DH public key generation succeeded.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE DH public key generation failed.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE PublicKeySize is not large enough.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync**/
45e9809aff7304721fddb95654901b32195c9c7avboxsyncBOOLEAN
45e9809aff7304721fddb95654901b32195c9c7avboxsyncEFIAPI
45e9809aff7304721fddb95654901b32195c9c7avboxsyncDhGenerateKey (
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN OUT VOID *DhContext,
45e9809aff7304721fddb95654901b32195c9c7avboxsync OUT UINT8 *PublicKey,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN OUT UINTN *PublicKeySize
45e9809aff7304721fddb95654901b32195c9c7avboxsync )
45e9809aff7304721fddb95654901b32195c9c7avboxsync{
45e9809aff7304721fddb95654901b32195c9c7avboxsync BOOLEAN RetVal;
45e9809aff7304721fddb95654901b32195c9c7avboxsync DH *Dh;
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync // Check input parameters.
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (DhContext == NULL || PublicKeySize == NULL) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync return FALSE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (PublicKey == NULL && *PublicKeySize != 0) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync return FALSE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync Dh = (DH *) DhContext;
45e9809aff7304721fddb95654901b32195c9c7avboxsync *PublicKeySize = 0;
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync RetVal = (BOOLEAN) DH_generate_key (DhContext);
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (RetVal) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync BN_bn2bin (Dh->pub_key, PublicKey);
45e9809aff7304721fddb95654901b32195c9c7avboxsync *PublicKeySize = BN_num_bytes (Dh->pub_key);
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync return RetVal;
45e9809aff7304721fddb95654901b32195c9c7avboxsync}
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync/**
45e9809aff7304721fddb95654901b32195c9c7avboxsync Computes exchanged common key.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync Given peer's public key, this function computes the exchanged common key, based on its own
45e9809aff7304721fddb95654901b32195c9c7avboxsync context including value of prime modulus and random secret exponent.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync If DhContext is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If PeerPublicKey is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If KeySize is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync If KeySize is large enough but Key is NULL, then return FALSE.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in, out] DhContext Pointer to the DH context.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in] PeerPublicKey Pointer to the peer's public key.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in] PeerPublicKeySize Size of peer's public key in bytes.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[out] Key Pointer to the buffer to receive generated key.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @param[in, out] KeySize On input, the size of Key buffer in bytes.
45e9809aff7304721fddb95654901b32195c9c7avboxsync On output, the size of data returned in Key buffer in bytes.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval TRUE DH exchanged key generation succeeded.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE DH exchanged key generation failed.
45e9809aff7304721fddb95654901b32195c9c7avboxsync @retval FALSE KeySize is not large enough.
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync**/
45e9809aff7304721fddb95654901b32195c9c7avboxsyncBOOLEAN
45e9809aff7304721fddb95654901b32195c9c7avboxsyncEFIAPI
45e9809aff7304721fddb95654901b32195c9c7avboxsyncDhComputeKey (
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN OUT VOID *DhContext,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN CONST UINT8 *PeerPublicKey,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN UINTN PeerPublicKeySize,
45e9809aff7304721fddb95654901b32195c9c7avboxsync OUT UINT8 *Key,
45e9809aff7304721fddb95654901b32195c9c7avboxsync IN OUT UINTN *KeySize
45e9809aff7304721fddb95654901b32195c9c7avboxsync )
45e9809aff7304721fddb95654901b32195c9c7avboxsync{
45e9809aff7304721fddb95654901b32195c9c7avboxsync BIGNUM *Bn;
45e9809aff7304721fddb95654901b32195c9c7avboxsync
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync // Check input parameters.
45e9809aff7304721fddb95654901b32195c9c7avboxsync //
45e9809aff7304721fddb95654901b32195c9c7avboxsync if (DhContext == NULL || PeerPublicKey == NULL || KeySize == NULL) {
45e9809aff7304721fddb95654901b32195c9c7avboxsync return FALSE;
45e9809aff7304721fddb95654901b32195c9c7avboxsync }
45e9809aff7304721fddb95654901b32195c9c7avboxsync
if (Key == NULL && *KeySize != 0) {
return FALSE;
}
Bn = BN_bin2bn (PeerPublicKey, (UINT32) PeerPublicKeySize, NULL);
*KeySize = (BOOLEAN) DH_compute_key (Key, Bn, DhContext);
BN_free (Bn);
return TRUE;
}