214
* Compute the secure session id, two encryption keys, and four MAC keys
215
* given our DH key and their DH public key.
217
gcry_error_t otrl_dh_compute_v2_auth_keys(const DH_keypair *our_dh,
218
gcry_mpi_t their_pub, unsigned char *sessionid, size_t *sessionidlenp,
219
gcry_cipher_hd_t *enc_c, gcry_cipher_hd_t *enc_cp,
220
gcry_md_hd_t *mac_m1, gcry_md_hd_t *mac_m1p,
221
gcry_md_hd_t *mac_m2, gcry_md_hd_t *mac_m2p)
225
unsigned char *sdata;
226
unsigned char *hashdata;
227
unsigned char ctr[16];
228
gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
238
if (our_dh->groupid != DH1536_GROUP_ID) {
239
/* Invalid group id */
240
return gcry_error(GPG_ERR_INV_VALUE);
243
/* Check that their_pub is in range */
244
if (gcry_mpi_cmp_ui(their_pub, 2) < 0 ||
245
gcry_mpi_cmp(their_pub, DH1536_MODULUS_MINUS_2) > 0) {
247
return gcry_error(GPG_ERR_INV_VALUE);
250
/* Calculate the shared secret MPI */
251
s = gcry_mpi_new(DH1536_MOD_LEN_BITS);
252
gcry_mpi_powm(s, their_pub, our_dh->priv, DH1536_MODULUS);
254
/* Output it in the right format */
255
gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &slen, s);
256
sdata = gcry_malloc_secure(slen + 5);
259
return gcry_error(GPG_ERR_ENOMEM);
261
sdata[1] = (slen >> 24) & 0xff;
262
sdata[2] = (slen >> 16) & 0xff;
263
sdata[3] = (slen >> 8) & 0xff;
264
sdata[4] = slen & 0xff;
265
gcry_mpi_print(GCRYMPI_FMT_USG, sdata+5, slen, NULL, s);
268
/* Calculate the session id */
269
hashdata = gcry_malloc_secure(32);
272
return gcry_error(GPG_ERR_ENOMEM);
275
gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
276
memmove(sessionid, hashdata, 8);
279
/* Calculate the encryption keys */
281
gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
283
err = gcry_cipher_open(enc_c, GCRY_CIPHER_AES,
284
GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
286
err = gcry_cipher_setkey(*enc_c, hashdata, 16);
288
err = gcry_cipher_setctr(*enc_c, ctr, 16);
291
err = gcry_cipher_open(enc_cp, GCRY_CIPHER_AES,
292
GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
294
err = gcry_cipher_setkey(*enc_cp, hashdata+16, 16);
296
err = gcry_cipher_setctr(*enc_cp, ctr, 16);
299
/* Calculate the MAC keys */
301
gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
302
err = gcry_md_open(mac_m1, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
304
err = gcry_md_setkey(*mac_m1, hashdata, 32);
308
gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
309
err = gcry_md_open(mac_m2, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
311
err = gcry_md_setkey(*mac_m2, hashdata, 32);
315
gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
316
err = gcry_md_open(mac_m1p, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
318
err = gcry_md_setkey(*mac_m1p, hashdata, 32);
322
gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
323
err = gcry_md_open(mac_m2p, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
325
err = gcry_md_setkey(*mac_m2p, hashdata, 32);
330
return gcry_error(GPG_ERR_NO_ERROR);
333
gcry_cipher_close(*enc_c);
334
gcry_cipher_close(*enc_cp);
335
gcry_md_close(*mac_m1);
336
gcry_md_close(*mac_m1p);
337
gcry_md_close(*mac_m2);
338
gcry_md_close(*mac_m2p);
351
* Compute the secure session id, given our DH key and their DH public
354
gcry_error_t otrl_dh_compute_v1_session_id(const DH_keypair *our_dh,
355
gcry_mpi_t their_pub, unsigned char *sessionid, size_t *sessionidlenp,
356
OtrlSessionIdHalf *halfp)
360
unsigned char *sdata;
361
unsigned char *hashdata;
363
if (our_dh->groupid != DH1536_GROUP_ID) {
364
/* Invalid group id */
365
return gcry_error(GPG_ERR_INV_VALUE);
368
/* Check that their_pub is in range */
369
if (gcry_mpi_cmp_ui(their_pub, 2) < 0 ||
370
gcry_mpi_cmp(their_pub, DH1536_MODULUS_MINUS_2) > 0) {
372
return gcry_error(GPG_ERR_INV_VALUE);
375
/* Calculate the shared secret MPI */
376
s = gcry_mpi_new(DH1536_MOD_LEN_BITS);
377
gcry_mpi_powm(s, their_pub, our_dh->priv, DH1536_MODULUS);
379
/* Output it in the right format */
380
gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &slen, s);
381
sdata = gcry_malloc_secure(slen + 5);
384
return gcry_error(GPG_ERR_ENOMEM);
386
sdata[1] = (slen >> 24) & 0xff;
387
sdata[2] = (slen >> 16) & 0xff;
388
sdata[3] = (slen >> 8) & 0xff;
389
sdata[4] = slen & 0xff;
390
gcry_mpi_print(GCRYMPI_FMT_USG, sdata+5, slen, NULL, s);
393
/* Calculate the session id */
394
hashdata = gcry_malloc_secure(20);
397
return gcry_error(GPG_ERR_ENOMEM);
400
gcry_md_hash_buffer(GCRY_MD_SHA1, hashdata, sdata, slen+5);
401
memmove(sessionid, hashdata, 20);
404
/* Which half should be bold? */
405
if (gcry_mpi_cmp(our_dh->pub, their_pub) > 0) {
406
*halfp = OTRL_SESSIONID_SECOND_HALF_BOLD;
408
*halfp = OTRL_SESSIONID_FIRST_HALF_BOLD;
413
return gcry_error(GPG_ERR_NO_ERROR);
195
417
* Deallocate the contents of a DH_sesskeys (but not the DH_sesskeys