00001
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
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);
00061 int cipherkeybits = params->cipherkeybits;
00062 int mackeybits = params->mackeybits;
00063
00064
00065 if ((keybits & 31) != 0)
00066 return 0;
00067
00068
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
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
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
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
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
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
00184 }
00185
00188 static int dhaes_pContextSetup(dhaes_pContext* ctxt, const mp32number* privkey, const mp32number* pubkey, const mp32number* message, cipherOperation op)
00189
00190 {
00191 register int rc;
00192
00193 mp32number secret;
00194 mp32number digest;
00195
00196
00197 mp32nzero(&secret);
00198 if (dlsvdp_pDHSecret(&ctxt->param, privkey, pubkey, &secret))
00199
00200 return -1;
00201
00202
00203
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
00211 mp32nwipe(&secret);
00212 mp32nfree(&secret);
00213
00225
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
00242
00243 setup_end:
00244 mp32nwipe(&digest);
00245 mp32nfree(&digest);
00246
00247
00248 return rc;
00249
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
00260 mp32nzero(&ephemeralPrivateKey);
00261 (void) dldp_pPair(&ctxt->param, rng, &ephemeralPrivateKey, ephemeralPublicKey);
00262
00263
00264 if (dhaes_pContextSetup(ctxt, &ephemeralPrivateKey, &ctxt->pub, ephemeralPublicKey, ENCRYPT))
00265 goto encrypt_end;
00266
00267
00268 paddedtext = pkcs5PadCopy(ctxt->cipher.algo->blocksize, cleartext);
00269 if (paddedtext == (memchunk*) 0)
00270 goto encrypt_end;
00271
00272
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
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
00302 return ciphertext;
00303
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
00312 if (dhaes_pContextSetup(ctxt, &ctxt->pri, ephemeralPublicKey, ephemeralPublicKey, DECRYPT))
00313 goto decrypt_end;
00314
00315
00316 if (keyedHashFunctionContextUpdateMC(&ctxt->mac, ciphertext))
00317 goto decrypt_end;
00318
00319 if (keyedHashFunctionContextDigestMatch(&ctxt->mac, mac) == 0)
00320 goto decrypt_end;
00321
00322
00323
00324 paddedtext = (memchunk*) calloc(1, sizeof(memchunk));
00325
00326
00327 if (paddedtext == (memchunk*) 0)
00328 goto decrypt_end;
00329
00330 paddedtext->size = ciphertext->size;
00331
00332 paddedtext->data = (byte*) malloc(ciphertext->size);
00333
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
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
00360 return cleartext;
00361
00362 }