Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

beecrypt/dhaes.c

Go to the documentation of this file.
00001 
00030 /*
00031  * Copyright (c) 2000, 2001 Virtual Unlimited, B.V.
00032  *
00033  * Author: Bob Deblier <bob@virtualunlimited.com>
00034  *
00035  * This library is free software; you can redistribute it and/or
00036  * modify it under the terms of the GNU Lesser General Public
00037  * License as published by the Free Software Foundation; either
00038  * version 2.1 of the License, or (at your option) any later version.
00039  *
00040  * This library is distributed in the hope that it will be useful,
00041  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00042  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00043  * Lesser General Public License for more details.
00044  *
00045  * You should have received a copy of the GNU Lesser General Public
00046  * License along with this library; if not, write to the Free Software
00047  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00048  *
00049  */
00050 
00051 #include "system.h"
00052 #include "dhaes.h"
00053 #include "dlsvdp-dh.h"
00054 #include "blockmode.h"
00055 #include "blockpad.h"
00056 #include "debug.h"
00057 
00058 int dhaes_pUsable(const dhaes_pParameters* params)
00059 {
00060         int keybits = (params->hash->digestsize << 3); /* digestsize in bytes times 8 bits */
00061         int cipherkeybits = params->cipherkeybits;
00062         int mackeybits = params->mackeybits;
00063 
00064         /* test if keybits is a multiple of 32 */
00065         if ((keybits & 31) != 0)
00066                 return 0;
00067 
00068         /* test if cipherkeybits + mackeybits < keybits */
00069         if ((cipherkeybits + mackeybits) > keybits)
00070                 return 0;
00071 
00072         if (mackeybits == 0)
00073         {
00074                 if (cipherkeybits == 0)
00075                         cipherkeybits = mackeybits = (((uint32)keybits) >> 1);
00076                 else
00077                         mackeybits = keybits - cipherkeybits;
00078         }
00079 
00080         /* test if keybits length is appropriate for cipher */
00081         if ((cipherkeybits < params->cipher->keybitsmin) ||
00082                         (cipherkeybits > params->cipher->keybitsmax))
00083                 return 0;
00084 
00085         if (((cipherkeybits - params->cipher->keybitsmin) % params->cipher->keybitsinc) != 0)
00086                 return 0;
00087 
00088         /* test if keybits length is appropriate for mac */
00089         if ((mackeybits < params->mac->keybitsmin) ||
00090                         (params->mackeybits > params->mac->keybitsmax))
00091                 return 0;
00092 
00093         if (((mackeybits - params->mac->keybitsmin) % params->mac->keybitsinc) != 0)
00094                 return 0;
00095 
00096         return 1;
00097 }
00098 
00099 int dhaes_pContextInit(dhaes_pContext* ctxt, const dhaes_pParameters* params)
00100 {
00101         if (ctxt == (dhaes_pContext*) 0)
00102                 return -1;
00103 
00104         if (params == (dhaes_pParameters*) 0)
00105                 return -1;
00106 
00107         if (params->param == (dldp_p*) 0)
00108                 return -1;
00109 
00110         if (params->hash == (hashFunction*) 0)
00111                 return -1;
00112 
00113         if (params->cipher == (blockCipher*) 0)
00114                 return -1;
00115 
00116         if (params->mac == (keyedHashFunction*) 0)
00117                 return -1;
00118 
00119         if (!dhaes_pUsable(params))
00120                 return -1;
00121 
00122         (void) dldp_pInit(&ctxt->param);
00123         (void) dldp_pCopy(&ctxt->param, params->param);
00124 
00125         mp32nzero(&ctxt->pub);
00126         mp32nzero(&ctxt->pri);
00127 
00128         /*@-modobserver@*/
00129         if (hashFunctionContextInit(&ctxt->hash, params->hash))
00130                 return -1;
00131 
00132         if (blockCipherContextInit(&ctxt->cipher, params->cipher))
00133                 return -1;
00134 
00135         if (keyedHashFunctionContextInit(&ctxt->mac, params->mac))
00136                 return -1;
00137         /*@=modobserver@*/
00138 
00139         ctxt->cipherkeybits = params->cipherkeybits;
00140         ctxt->mackeybits = params->mackeybits;
00141 
00142         return 0;
00143 }
00144 
00145 int dhaes_pContextInitDecrypt(dhaes_pContext* ctxt, const dhaes_pParameters* params, const mp32number* pri)
00146 {
00147         if (dhaes_pContextInit(ctxt, params))
00148                 return -1;
00149 
00150         mp32ncopy(&ctxt->pri, pri);
00151 
00152         return 0;
00153 }
00154 
00155 int dhaes_pContextInitEncrypt(dhaes_pContext* ctxt, const dhaes_pParameters* params, const mp32number* pub)
00156 {
00157         if (dhaes_pContextInit(ctxt, params))
00158                 return -1;
00159 
00160         mp32ncopy(&ctxt->pub, pub);
00161 
00162         return 0;
00163 }
00164 
00165 int dhaes_pContextFree(dhaes_pContext* ctxt)
00166 {
00167         (void) dldp_pFree(&ctxt->param);
00168 
00169         mp32nfree(&ctxt->pub);
00170         mp32nfree(&ctxt->pri);
00171 
00172         /*@-mustfree -modobserver @*/ /* ctxt is OK */
00173         if (hashFunctionContextFree(&ctxt->hash))
00174                 return -1;
00175 
00176         if (blockCipherContextFree(&ctxt->cipher))
00177                 return -1;
00178 
00179         if (keyedHashFunctionContextFree(&ctxt->mac))
00180                 return -1;
00181 
00182         return 0;
00183         /*@=mustfree =modobserver @*/
00184 }
00185 
00188 static int dhaes_pContextSetup(dhaes_pContext* ctxt, const mp32number* privkey, const mp32number* pubkey, const mp32number* message, cipherOperation op)
00189         /*@modifies ctxt @*/
00190 {
00191         register int rc;
00192 
00193         mp32number secret;
00194         mp32number digest;
00195 
00196         /* compute the shared secret, Diffie-Hellman style */
00197         mp32nzero(&secret);
00198         if (dlsvdp_pDHSecret(&ctxt->param, privkey, pubkey, &secret))
00199                 /*@-mustfree@*/ /* FIX: secret.data leak? */
00200                 return -1;
00201                 /*@=mustfree@*/
00202 
00203         /* compute the hash of the message (ephemeral public) key and the shared secret */
00204         mp32nzero(&digest);
00205         (void) hashFunctionContextReset     (&ctxt->hash);
00206         (void) hashFunctionContextUpdateMP32(&ctxt->hash, message);
00207         (void) hashFunctionContextUpdateMP32(&ctxt->hash, &secret);
00208         (void) hashFunctionContextDigest    (&ctxt->hash, &digest);
00209 
00210         /* we don't need the secret anymore */
00211         mp32nwipe(&secret);
00212         mp32nfree(&secret);
00213 
00225         /*@-usedef@*/   /* LCL: digest already set */
00226         if (digest.size > 0)
00227         {
00228                 uint32* mackey = digest.data;
00229                 uint32* cipherkey = digest.data + (((uint32)(ctxt->mackeybits + 31)) >> 5);
00230 
00231                 if ((rc = keyedHashFunctionContextSetup(&ctxt->mac, mackey, ctxt->mackeybits)))
00232                         goto setup_end;
00233 
00234                 if ((rc = blockCipherContextSetup(&ctxt->cipher, cipherkey, ctxt->cipherkeybits, op)))
00235                         goto setup_end;
00236 
00237                 rc = 0;
00238         }
00239         else
00240                 rc = -1;
00241         /*@=usedef@*/
00242 
00243 setup_end:
00244         mp32nwipe(&digest);
00245         mp32nfree(&digest);
00246 
00247         /*@-mustfree@*/ /* {secret,digest}.data are OK */
00248         return rc;
00249         /*@=mustfree@*/
00250 }
00251 
00252 memchunk* dhaes_pContextEncrypt(dhaes_pContext* ctxt, mp32number* ephemeralPublicKey, mp32number* mac, const memchunk* cleartext, randomGeneratorContext* rng)
00253 {
00254         memchunk* ciphertext = (memchunk*) 0;
00255         memchunk* paddedtext;
00256 
00257         mp32number ephemeralPrivateKey;
00258 
00259         /* make the ephemeral keypair */
00260         mp32nzero(&ephemeralPrivateKey);
00261         (void) dldp_pPair(&ctxt->param, rng, &ephemeralPrivateKey, ephemeralPublicKey);
00262 
00263         /* Setup the key and initialize the mac and the blockcipher */
00264         if (dhaes_pContextSetup(ctxt, &ephemeralPrivateKey, &ctxt->pub, ephemeralPublicKey, ENCRYPT))
00265                 goto encrypt_end;
00266 
00267         /* add pkcs-5 padding */
00268         paddedtext = pkcs5PadCopy(ctxt->cipher.algo->blocksize, cleartext);
00269         if (paddedtext == (memchunk*) 0)
00270                 goto encrypt_end;
00271 
00272         /* encrypt the memchunk in CBC mode */
00273         if (blockEncrypt(ctxt->cipher.algo, ctxt->cipher.param, CBC, paddedtext->size / ctxt->cipher.algo->blocksize, (uint32*) paddedtext->data, (const uint32*) paddedtext->data))
00274         {
00275                 free(paddedtext->data);
00276                 free(paddedtext);
00277                 goto encrypt_end;
00278         }
00279 
00280         /* Compute the mac */
00281         if (keyedHashFunctionContextUpdateMC(&ctxt->mac, paddedtext))
00282         {
00283                 free(paddedtext->data);
00284                 free(paddedtext);
00285                 goto encrypt_end;
00286         }
00287 
00288         if (keyedHashFunctionContextDigest(&ctxt->mac, mac))
00289         {
00290                 free(paddedtext->data);
00291                 free(paddedtext);
00292                 goto encrypt_end;
00293         }
00294 
00295         ciphertext = paddedtext;
00296 
00297 encrypt_end:
00298         mp32nwipe(&ephemeralPrivateKey);
00299         mp32nfree(&ephemeralPrivateKey);
00300 
00301         /*@-mustfree@*/ /* ephemeralPrivateKey.data is OK */
00302         return ciphertext;
00303         /*@=mustfree@*/
00304 }
00305 
00306 memchunk* dhaes_pContextDecrypt(dhaes_pContext* ctxt, const mp32number* ephemeralPublicKey, const mp32number* mac, const memchunk* ciphertext)
00307 {
00308         memchunk* cleartext = (memchunk*) 0;
00309         memchunk* paddedtext;
00310 
00311         /* Setup the key and initialize the mac and the blockcipher */
00312         if (dhaes_pContextSetup(ctxt, &ctxt->pri, ephemeralPublicKey, ephemeralPublicKey, DECRYPT))
00313                 goto decrypt_end;
00314 
00315         /* Verify the mac */
00316         if (keyedHashFunctionContextUpdateMC(&ctxt->mac, ciphertext))
00317                 goto decrypt_end;
00318 
00319         if (keyedHashFunctionContextDigestMatch(&ctxt->mac, mac) == 0)
00320                 goto decrypt_end;
00321 
00322         /* decrypt the memchunk with CBC mode */
00323         /*@-sizeoftype@*/
00324         paddedtext = (memchunk*) calloc(1, sizeof(memchunk));
00325         /*@=sizeoftype@*/
00326 
00327         if (paddedtext == (memchunk*) 0)
00328                 goto decrypt_end;
00329 
00330         paddedtext->size = ciphertext->size;
00331         /*@-mustfree@*/ /* paddedtext->data is OK */
00332         paddedtext->data = (byte*) malloc(ciphertext->size);
00333         /*@=mustfree@*/
00334 
00335         if (paddedtext->data == (byte*) 0)
00336         {
00337                 free(paddedtext);
00338                 goto decrypt_end;
00339         }
00340 
00341         if (blockDecrypt(ctxt->cipher.algo, ctxt->cipher.param, CBC, paddedtext->size / ctxt->cipher.algo->blocksize, (uint32*) paddedtext->data, (const uint32*) ciphertext->data))
00342         {
00343                 free(paddedtext->data);
00344                 free(paddedtext);
00345                 goto decrypt_end;
00346         }
00347 
00348         /* remove pkcs-5 padding */
00349         cleartext = pkcs5Unpad(ctxt->cipher.algo->blocksize, paddedtext);
00350 
00351         if (cleartext == (memchunk*) 0)
00352         {
00353                 free(paddedtext->data);
00354                 free(paddedtext);
00355         }
00356 
00357 decrypt_end:
00358 
00359         /*@-usereleased@*/ /* LCL: cleartext released??? */
00360         return cleartext;
00361         /*@=usereleased@*/
00362 }

Generated on Wed Sep 4 12:49:47 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002