~ubuntu-branches/ubuntu/oneiric/libotr/oneiric-security

« back to all changes in this revision

Viewing changes to src/dh.c

  • Committer: Bazaar Package Importer
  • Author(s): Thibaut VARENE
  • Date: 2006-01-02 19:52:18 UTC
  • mfrom: (2.1.1 dapper)
  • Revision ID: james.westby@ubuntu.com-20060102195218-wb8803196y9mycx6
Tags: 3.0.0-2
Fix typo: "malformed messahes" (Closes: #345400)

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
static const int DH1536_MOD_LEN_BYTES = 192;
41
41
 
42
42
static gcry_mpi_t DH1536_MODULUS = NULL;
 
43
static gcry_mpi_t DH1536_MODULUS_MINUS_2 = NULL;
43
44
static gcry_mpi_t DH1536_GENERATOR = NULL;
44
45
 
45
46
/*
51
52
    gcry_mpi_scan(&DH1536_MODULUS, GCRYMPI_FMT_HEX, DH1536_MODULUS_S, 0, NULL);
52
53
    gcry_mpi_scan(&DH1536_GENERATOR, GCRYMPI_FMT_HEX, DH1536_GENERATOR_S,
53
54
            0, NULL);
 
55
    DH1536_MODULUS_MINUS_2 = gcry_mpi_new(DH1536_MOD_LEN_BITS);
 
56
    gcry_mpi_sub_ui(DH1536_MODULUS_MINUS_2, DH1536_MODULUS, 2);
 
57
}
 
58
 
 
59
/*
 
60
 * Initialize the fields of a DH keypair.
 
61
 */
 
62
void otrl_dh_keypair_init(DH_keypair *kp)
 
63
{
 
64
    kp->groupid = 0;
 
65
    kp->priv = NULL;
 
66
    kp->pub = NULL;
 
67
}
 
68
 
 
69
/*
 
70
 * Copy a DH_keypair.
 
71
 */
 
72
void otrl_dh_keypair_copy(DH_keypair *dst, const DH_keypair *src)
 
73
{
 
74
    dst->groupid = src->groupid;
 
75
    dst->priv = gcry_mpi_copy(src->priv);
 
76
    dst->pub = gcry_mpi_copy(src->pub);
54
77
}
55
78
 
56
79
/*
94
117
 * Construct session keys from a DH keypair and someone else's public
95
118
 * key.
96
119
 */
97
 
gcry_error_t otrl_dh_session(DH_sesskeys *sess, DH_keypair *kp, gcry_mpi_t y)
 
120
gcry_error_t otrl_dh_session(DH_sesskeys *sess, const DH_keypair *kp,
 
121
        gcry_mpi_t y)
98
122
{
99
123
    gcry_mpi_t gab;
100
124
    size_t gablen;
128
152
    gcry_mpi_print(GCRYMPI_FMT_USG, gabdata+5, gablen, NULL, gab);
129
153
    gcry_mpi_release(gab);
130
154
 
131
 
    /* Calculate the session id */
132
155
    hashdata = gcry_malloc_secure(20);
133
156
    if (!hashdata) {
134
157
        gcry_free(gabdata);
135
158
        return gcry_error(GPG_ERR_ENOMEM);
136
159
    }
137
 
    gabdata[0] = 0x00;
138
 
    gcry_md_hash_buffer(GCRY_MD_SHA1, sess->sessionid, gabdata, gablen+5);
139
160
 
140
161
    /* Are we the "high" or "low" end of the connection? */
141
162
    if ( gcry_mpi_cmp(kp->pub, y) > 0 ) {
142
 
        sess->dir = SESS_DIR_HIGH;
143
163
        sendbyte = 0x01;
144
164
        rcvbyte = 0x02;
145
165
    } else {
146
 
        sess->dir = SESS_DIR_LOW;
147
166
        sendbyte = 0x02;
148
167
        rcvbyte = 0x01;
149
168
    }
192
211
}
193
212
 
194
213
/*
 
214
 * Compute the secure session id, two encryption keys, and four MAC keys
 
215
 * given our DH key and their DH public key.
 
216
 */
 
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)
 
222
{
 
223
    gcry_mpi_t s;
 
224
    size_t slen;
 
225
    unsigned char *sdata;
 
226
    unsigned char *hashdata;
 
227
    unsigned char ctr[16];
 
228
    gcry_error_t err = gcry_error(GPG_ERR_NO_ERROR);
 
229
 
 
230
    *enc_c = NULL;
 
231
    *enc_cp = NULL;
 
232
    *mac_m1 = NULL;
 
233
    *mac_m1p = NULL;
 
234
    *mac_m2 = NULL;
 
235
    *mac_m2p = NULL;
 
236
    memset(ctr, 0, 16);
 
237
 
 
238
    if (our_dh->groupid != DH1536_GROUP_ID) {
 
239
        /* Invalid group id */
 
240
        return gcry_error(GPG_ERR_INV_VALUE);
 
241
    }
 
242
 
 
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) {
 
246
        /* Invalid pubkey */
 
247
        return gcry_error(GPG_ERR_INV_VALUE);
 
248
    }
 
249
 
 
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);
 
253
 
 
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);
 
257
    if (!sdata) {
 
258
        gcry_mpi_release(s);
 
259
        return gcry_error(GPG_ERR_ENOMEM);
 
260
    }
 
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);
 
266
    gcry_mpi_release(s);
 
267
 
 
268
    /* Calculate the session id */
 
269
    hashdata = gcry_malloc_secure(32);
 
270
    if (!hashdata) {
 
271
        gcry_free(sdata);
 
272
        return gcry_error(GPG_ERR_ENOMEM);
 
273
    }
 
274
    sdata[0] = 0x00;
 
275
    gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
 
276
    memmove(sessionid, hashdata, 8);
 
277
    *sessionidlenp = 8;
 
278
 
 
279
    /* Calculate the encryption keys */
 
280
    sdata[0] = 0x01;
 
281
    gcry_md_hash_buffer(GCRY_MD_SHA256, hashdata, sdata, slen+5);
 
282
 
 
283
    err = gcry_cipher_open(enc_c, GCRY_CIPHER_AES,
 
284
            GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
 
285
    if (err) goto err;
 
286
    err = gcry_cipher_setkey(*enc_c, hashdata, 16);
 
287
    if (err) goto err;
 
288
    err = gcry_cipher_setctr(*enc_c, ctr, 16);
 
289
    if (err) goto err;
 
290
 
 
291
    err = gcry_cipher_open(enc_cp, GCRY_CIPHER_AES,
 
292
            GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
 
293
    if (err) goto err;
 
294
    err = gcry_cipher_setkey(*enc_cp, hashdata+16, 16);
 
295
    if (err) goto err;
 
296
    err = gcry_cipher_setctr(*enc_cp, ctr, 16);
 
297
    if (err) goto err;
 
298
 
 
299
    /* Calculate the MAC keys */
 
300
    sdata[0] = 0x02;
 
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);
 
303
    if (err) goto err;
 
304
    err = gcry_md_setkey(*mac_m1, hashdata, 32);
 
305
    if (err) goto err;
 
306
 
 
307
    sdata[0] = 0x03;
 
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);
 
310
    if (err) goto err;
 
311
    err = gcry_md_setkey(*mac_m2, hashdata, 32);
 
312
    if (err) goto err;
 
313
 
 
314
    sdata[0] = 0x04;
 
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);
 
317
    if (err) goto err;
 
318
    err = gcry_md_setkey(*mac_m1p, hashdata, 32);
 
319
    if (err) goto err;
 
320
 
 
321
    sdata[0] = 0x05;
 
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);
 
324
    if (err) goto err;
 
325
    err = gcry_md_setkey(*mac_m2p, hashdata, 32);
 
326
    if (err) goto err;
 
327
 
 
328
    gcry_free(sdata);
 
329
    gcry_free(hashdata);
 
330
    return gcry_error(GPG_ERR_NO_ERROR);
 
331
 
 
332
err:
 
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);
 
339
    *enc_c = NULL;
 
340
    *enc_cp = NULL;
 
341
    *mac_m1 = NULL;
 
342
    *mac_m1p = NULL;
 
343
    *mac_m2 = NULL;
 
344
    *mac_m2p = NULL;
 
345
    gcry_free(sdata);
 
346
    gcry_free(hashdata);
 
347
    return err;
 
348
}
 
349
 
 
350
/*
 
351
 * Compute the secure session id, given our DH key and their DH public
 
352
 * key.
 
353
 */
 
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)
 
357
{
 
358
    gcry_mpi_t s;
 
359
    size_t slen;
 
360
    unsigned char *sdata;
 
361
    unsigned char *hashdata;
 
362
 
 
363
    if (our_dh->groupid != DH1536_GROUP_ID) {
 
364
        /* Invalid group id */
 
365
        return gcry_error(GPG_ERR_INV_VALUE);
 
366
    }
 
367
 
 
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) {
 
371
        /* Invalid pubkey */
 
372
        return gcry_error(GPG_ERR_INV_VALUE);
 
373
    }
 
374
 
 
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);
 
378
 
 
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);
 
382
    if (!sdata) {
 
383
        gcry_mpi_release(s);
 
384
        return gcry_error(GPG_ERR_ENOMEM);
 
385
    }
 
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);
 
391
    gcry_mpi_release(s);
 
392
 
 
393
    /* Calculate the session id */
 
394
    hashdata = gcry_malloc_secure(20);
 
395
    if (!hashdata) {
 
396
        gcry_free(sdata);
 
397
        return gcry_error(GPG_ERR_ENOMEM);
 
398
    }
 
399
    sdata[0] = 0x00;
 
400
    gcry_md_hash_buffer(GCRY_MD_SHA1, hashdata, sdata, slen+5);
 
401
    memmove(sessionid, hashdata, 20);
 
402
    *sessionidlenp = 20;
 
403
 
 
404
    /* Which half should be bold? */
 
405
    if (gcry_mpi_cmp(our_dh->pub, their_pub) > 0) {
 
406
        *halfp = OTRL_SESSIONID_SECOND_HALF_BOLD;
 
407
    } else {
 
408
        *halfp = OTRL_SESSIONID_FIRST_HALF_BOLD;
 
409
    }
 
410
 
 
411
    gcry_free(hashdata);
 
412
    gcry_free(sdata);
 
413
    return gcry_error(GPG_ERR_NO_ERROR);
 
414
}
 
415
 
 
416
/*
195
417
 * Deallocate the contents of a DH_sesskeys (but not the DH_sesskeys
196
418
 * itself)
197
419
 */
214
436
    sess->sendmac = NULL;
215
437
    sess->rcvenc = NULL;
216
438
    sess->rcvmac = NULL;
217
 
    memset(sess->sessionid, 0, 20);
218
439
    memset(sess->sendctr, 0, 16);
219
440
    memset(sess->rcvctr, 0, 16);
220
441
    memset(sess->sendmackey, 0, 20);
234
455
 
235
456
/* Compare two counter values (8 bytes each).  Return 0 if ctr1 == ctr2,
236
457
 * < 0 if ctr1 < ctr2 (as unsigned 64-bit values), > 0 if ctr1 > ctr2. */
237
 
int otrl_dh_cmpctr(unsigned char *ctr1, unsigned char *ctr2)
 
458
int otrl_dh_cmpctr(const unsigned char *ctr1, const unsigned char *ctr2)
238
459
{
239
460
    int i;
240
461
    for (i=0;i<8;++i) {