OSDN Git Service

fixed for Ubuntu 12.04
[openpts/openpts.git] / src / nonce.c
1 /*
2  * This file is part of the OpenPTS project.
3  *
4  * The Initial Developer of the Original Code is International
5  * Business Machines Corporation. Portions created by IBM
6  * Corporation are Copyright (C) 2010 International Business
7  * Machines Corporation. All Rights Reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the Common Public License as published by
11  * IBM Corporation; either version 1 of the License, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * Common Public License for more details.
18  *
19  * You should have received a copy of the Common Public License
20  * along with this program; if not, a copy can be viewed at
21  * http://www.opensource.org/licenses/cpl1.0.php.
22  */
23
24 /**
25  * \file src/nonce.c
26  * \brief calc D-H nonce
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-08-19
29  * cleanup 2012-01-05 SM
30  *
31  * PTS IF-M DH-Nonce protocol
32  *
33  * D-H Nonce Parameters Request
34  *   nonce len
35  *   D-H group set
36  *   
37  * D-H Nonce Parameters Responce
38  *   nonce length
39  *   Selected D-H Group
40  *   Hash Algorithm Set
41  *   D-H Responder Nonce
42  *   D-H Responder Public Value
43  *
44  * D-H Nonce Finish
45  *   nonce length
46  *   Selected Hash Algorithm
47  *   D-H Initiater Public Value
48  *   D-H Initiater Nonce 
49  *
50  *  http://www.ietf.org/rfc/rfc2409.txt  IKE group 1-4
51  *  http://www.ietf.org/rfc/rfc3526.txt  IKE group 5-18
52  *  http://www.ietf.org/rfc/rfc4753.txt  IKE group 19-21?
53  *
54  * nonce size 16-255 (8bit)
55  * TODO random nonce
56  */
57
58
59
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63
64 #include <openssl/sha.h>
65 #include <openssl/dh.h>
66
67 #include <openpts.h>
68
69 #define DH_NONCE_SIZE  20
70 #define DH_GROUP_2_SIZE  128
71 #define DH_GROUP_5_SIZE  192
72 #define DH_GROUP_14_SIZE 256
73
74 char *group2 =
75         "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
76         "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
77         "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
78         "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
79         "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
80         "FFFFFFFF" "FFFFFFFF";
81
82 char *group5 =
83         "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
84         "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
85         "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
86         "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
87         "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
88         "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
89         "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
90         "670C354E" "4ABC9804" "F1746C08" "CA237327" "FFFFFFFF" "FFFFFFFF";
91
92 char *group14 =
93         "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
94         "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
95         "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
96         "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
97         "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
98         "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
99         "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
100         "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
101         "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
102         "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
103         "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
104
105 /**
106  * New OPENPTS_NONCE
107  *
108  * malloc -> free@freeNonceContext()
109  *  OPENPTS_NONCE ctx
110  *  ctx->req
111  *  ctx->res
112  *  ctx->fin
113  */
114 OPENPTS_NONCE *newNonceContext() {
115     OPENPTS_NONCE *ctx = NULL;
116
117     DEBUG_CAL("newNonceContext\n");
118
119     /* malloc */
120     ctx = xmalloc(sizeof(OPENPTS_NONCE));
121     if (ctx == NULL) {
122         LOG(LOG_ERR, "no memory");
123         return NULL;
124     }
125     memset(ctx, 0, sizeof(OPENPTS_NONCE));
126
127     /* malloc req */
128     ctx->req = (PTS_IF_M_DH_Nonce_Parameters_Request *)xmalloc(sizeof(PTS_IF_M_DH_Nonce_Parameters_Request));
129     if (ctx->req == NULL) {
130         LOG(LOG_ERR, "no memory");
131         xfree(ctx);
132         return NULL;
133     }
134     memset(ctx->req, 0, sizeof(PTS_IF_M_DH_Nonce_Parameters_Request));
135
136     /* malloc res */
137     ctx->res = xmalloc(sizeof(PTS_IF_M_DH_Nonce_Parameters_Responce));
138     if (ctx->res == NULL) {
139         LOG(LOG_ERR, "no memory");
140         xfree(ctx->req);
141         xfree(ctx);
142         return NULL;
143     }
144     memset(ctx->res, 0, sizeof(PTS_IF_M_DH_Nonce_Parameters_Responce));
145
146     /* malloc fin */
147     ctx->fin = xmalloc(sizeof(PTS_IF_M_DH_Nonce_Finish));
148     if (ctx->fin == NULL) {
149         LOG(LOG_ERR, "no memory");
150         xfree(ctx->req);
151         xfree(ctx->res);
152         xfree(ctx);
153         return NULL;
154     }
155     memset(ctx->fin, 0, sizeof(PTS_IF_M_DH_Nonce_Finish));
156
157     return ctx;
158 }
159
160 /**
161  * Free OPENPTS_NONCE
162  *
163  * free
164  *   ctx->req
165  *   ctx->res->dh_respondor_nonce
166  *   ctx->res->dh_respondor_public
167  *   ctx->res
168  *   ctx->fin->dh_initiator_nonce
169  *   ctx->fin->dh_initiator_public
170  *   ctx->fin
171  *   ctx->secret
172  *   ctx->nonce
173  */
174 int freeNonceContext(OPENPTS_NONCE *ctx) {
175     DEBUG_CAL("freeNonceContext\n");
176
177     /* check */
178     if (ctx == NULL) {
179         LOG(LOG_ERR, "null input");
180         return PTS_FATAL;
181     }
182
183     /* free req */
184     if (ctx->req != NULL) {
185         xfree(ctx->req);
186     }
187     /* free res */
188     if (ctx->res != NULL) {
189         if (ctx->res->dh_respondor_nonce != NULL) {
190             xfree(ctx->res->dh_respondor_nonce);
191         }
192         if (ctx->res->dh_respondor_public != NULL) {
193             xfree(ctx->res->dh_respondor_public);
194         }
195         xfree(ctx->res);
196     }
197     /* free fin */
198     if (ctx->fin != NULL) {
199         if (ctx->fin->dh_initiator_nonce != NULL) {
200             xfree(ctx->fin->dh_initiator_nonce);
201         }
202         if (ctx->fin->dh_initiator_public != NULL) {
203             xfree(ctx->fin->dh_initiator_public);
204         }
205         xfree(ctx->fin);
206     }
207     /* free secret */
208     if (ctx->secret != NULL) {
209         memset(ctx->secret, 0, ctx->secret_length);
210         xfree(ctx->secret);
211     }
212     /* free nonce */
213     if (ctx->nonce != NULL) {
214         xfree(ctx->nonce);
215     }
216
217     /* free DH */
218     if (ctx->dh != NULL) {
219         DH_free(ctx->dh);
220     }
221
222     xfree(ctx);
223
224     return PTS_SUCCESS;
225 }
226
227 /**
228  * Calc ExternalDataValue (=nonce)
229  *
230  *  nonce = HASH("1" | initiator's nonce | respondor's nonce | secret)
231  */
232 int calcExternalDataValue(OPENPTS_NONCE *ctx) {
233     SHA_CTX sha_ctx;
234     char c = '1';
235
236     /* check */
237     if (ctx == NULL) {
238         LOG(LOG_ERR, "null input");
239         return PTS_FATAL;
240     }
241
242     ctx->nonce_length = SHA1_DIGEST_SIZE;
243     ctx->nonce = xmalloc_assert(SHA1_DIGEST_SIZE);
244     if (ctx->nonce == NULL) {
245         LOG(LOG_ERR, "no memory");
246         return PTS_FATAL;
247     }
248
249     SHA1_Init(&sha_ctx);
250     SHA1_Update(&sha_ctx, &c, 1);
251     SHA1_Update(&sha_ctx, ctx->initiator_nonce, ctx->initiator_nonce_length);
252     SHA1_Update(&sha_ctx, ctx->respondor_nonce, ctx->respondor_nonce_length);
253     SHA1_Update(&sha_ctx, ctx->secret, ctx->secret_length);
254     SHA1_Final(ctx->nonce, &sha_ctx);
255
256     if (isDebugFlagSet(DEBUG_FLAG)) {
257         LOG(LOG_TODO, "calcExternalDataValue - nonce\n");
258         debugHex("\t\tinitiator_nonce:", ctx->initiator_nonce, ctx->initiator_nonce_length, "\n");
259         debugHex("\t\trespondor_nonce:", ctx->respondor_nonce, ctx->respondor_nonce_length, "\n");
260         debugHex("\t\tsecret         :", ctx->secret, ctx->secret_length, "\n");
261         debugHex("\t\tnonce          :", ctx->nonce, 20, "\n");
262     }
263
264     return PTS_SUCCESS;
265 }
266
267
268 /**
269  * Respondor
270  *
271  * malloc -> free@freeNonceContext()
272  *   res->dh_respondor_nonce
273  *   res->dh_respondor_public
274  */
275 int getDhResponce(OPENPTS_NONCE *ctx) {
276     int rc = 0;
277     BIGNUM *p, *g;
278     PTS_IF_M_DH_Nonce_Parameters_Request  *req;
279     PTS_IF_M_DH_Nonce_Parameters_Responce *res;
280
281     /* check */
282     if (ctx == NULL) {
283         LOG(LOG_ERR, "null input");
284         return PTS_FATAL;
285     }
286     req = ctx->req;
287     if (req == NULL) {
288         LOG(LOG_ERR, "null input");
289         return PTS_FATAL;
290     }
291     res = ctx->res;
292     if (res == NULL) {
293         LOG(LOG_ERR, "null input");
294         return PTS_FATAL;
295     }
296     if (req->reserved != 0) {
297         LOG(LOG_ERR, "reserved must be 0\n");
298         return PTS_INTERNAL_ERROR;
299     }
300
301     /* select nonce size */
302     if (req->min_nonce_len > 20) {
303         ctx->nonce_length = req->min_nonce_len;
304     } else {
305         ctx->nonce_length = 20;
306     }
307     res->nonce_length = ctx->nonce_length;
308
309     /* set DH Hash Alg */
310     res->hash_alg_set = DH_HASH_SHA1;
311     ctx->selected_hash_alg = DH_HASH_SHA1;
312
313     /* setup DH */
314     p = BN_new();
315     g = BN_new();
316     ctx->dh = DH_new();
317
318     /* select DH group */
319     if (req->dh_group_set & DH_GROUP_2) {
320         res->selected_dh_group = DH_GROUP_2;
321         ctx->selected_dh_group = DH_GROUP_2;
322         ctx->pubkey_length = DH_GROUP_2_SIZE;
323         BN_hex2bn(&p, group2);
324     } else if (req->dh_group_set & DH_GROUP_5) {
325         res->selected_dh_group = DH_GROUP_5;
326         ctx->selected_dh_group = DH_GROUP_5;
327         ctx->pubkey_length = DH_GROUP_5_SIZE;
328         BN_hex2bn(&p, group5);
329     } else if (req->dh_group_set & DH_GROUP_14) {
330         res->selected_dh_group = DH_GROUP_14;
331         ctx->selected_dh_group = DH_GROUP_14;
332         ctx->pubkey_length = DH_GROUP_14_SIZE;
333         BN_hex2bn(&p, group14);
334     } else {
335         res->selected_dh_group = 0;
336         LOG(LOG_ERR, "Unknown DH group set 0x%x", req->dh_group_set);
337         return PTS_DENIED;
338     }
339
340     BN_set_word(g, 2);
341
342     ctx->dh->p = BN_dup(p);
343     ctx->dh->g = BN_dup(g);
344
345     /* DH gen key */
346     rc = DH_generate_key(ctx->dh);
347
348     /* respondor nonce */
349
350     /* malloc */
351     res->dh_respondor_nonce = xmalloc(res->nonce_length);
352     if (res->dh_respondor_nonce == NULL) {
353         LOG(LOG_ERR, "dh_respondor_nonce is null");
354         return PTS_INTERNAL_ERROR;
355     }
356
357     /* set random */
358     rc = getRandom(res->dh_respondor_nonce, res->nonce_length);
359     if (rc != TSS_SUCCESS) {
360         LOG(LOG_ERR, "get random fail\n");
361         return PTS_INTERNAL_ERROR;
362     }
363
364     /* respondor nonce (local copy)*/
365     ctx->respondor_nonce_length = res->nonce_length;
366     ctx->respondor_nonce = res->dh_respondor_nonce;
367
368     /* pubkey */
369
370     /* malloc */
371     res->dh_respondor_public = xmalloc(DH_size(ctx->dh));
372     if (res->dh_respondor_public == NULL) {
373         LOG(LOG_ERR, "no memory");
374         return PTS_FATAL;
375     }
376
377     /* set */
378     BN_bn2bin(ctx->dh->pub_key, res->dh_respondor_public);
379     ctx->pubkey = res->dh_respondor_public;
380
381     /* reserved */
382     res->reserved[0] = 0;
383     res->reserved[1] = 0;
384     res->reserved[2] = 0;
385
386     /* free */
387     BN_free(p);
388     BN_free(g);
389     // DH_free(ctx->dh);
390
391     return PTS_SUCCESS;
392 }
393
394 /**
395  *
396  */
397 int setDhPubkeylength(OPENPTS_NONCE *ctx) {
398     PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
399
400     /* check */
401     if (ctx == NULL) {
402         LOG(LOG_ERR, "null input");
403         return PTS_FATAL;
404     }
405
406     /* select DH group */
407     if (res->selected_dh_group == DH_GROUP_2) {
408         ctx->pubkey_length = DH_GROUP_2_SIZE;
409     } else if (res->selected_dh_group == DH_GROUP_5) {
410         ctx->pubkey_length = DH_GROUP_5_SIZE;
411     } else if (res->selected_dh_group == DH_GROUP_14) {
412         ctx->pubkey_length = DH_GROUP_14_SIZE;
413     } else {
414         LOG(LOG_ERR, "Bad DH group 0x%x\n", res->selected_dh_group);
415         return PTS_DENIED;  // TODO
416     }
417
418     return PTS_SUCCESS;
419 }
420
421
422 /**
423  * Initiator
424  *
425  * malloc -> free@freeNonceContext()
426  *   fin->dh_initiator_nonce
427  *   fin->dh_initiator_public 
428  *   ctx->secret
429  */
430 int calcDh(OPENPTS_NONCE *ctx) {
431     int rc = 0;
432     BIGNUM *p, *g;
433     BIGNUM *pub_key;
434     PTS_IF_M_DH_Nonce_Parameters_Responce *res;
435     PTS_IF_M_DH_Nonce_Finish *fin;
436
437     /* check */
438     if (ctx == NULL) {
439         LOG(LOG_ERR, "null input");
440         return PTS_FATAL;
441     }
442     res = ctx->res;
443     if (res == NULL) {
444         LOG(LOG_ERR, "null input");
445         return PTS_FATAL;
446     }
447     fin = ctx->fin;
448     if (fin == NULL) {
449         LOG(LOG_ERR, "null input");
450         return PTS_FATAL;
451     }
452
453     if (res->reserved[0] != 0) {
454         // TODO check 1,2 too
455         LOG(LOG_ERR, "reserved must be 0\n");
456         return PTS_INTERNAL_ERROR;
457     }
458
459     /* set DH Hash Alg */
460     if (res->hash_alg_set & DH_HASH_SHA1) {
461         // OK
462         fin->selected_hash_alg = DH_HASH_SHA1;
463         ctx->selected_hash_alg = DH_HASH_SHA1;
464     } else {
465         LOG(LOG_ERR, "Bad DH hash set 0x%x\n", res->hash_alg_set);
466         return PTS_DENIED;
467     }
468
469     /* store respondor nonce */
470     ctx->respondor_nonce_length = res->nonce_length;
471     ctx->respondor_nonce = res->dh_respondor_nonce;
472
473     /* select initiator nonce size */
474     ctx->nonce_length = res->nonce_length;  // same length
475     fin->nonce_length = ctx->nonce_length;
476
477     /* setup DH */
478     p = BN_new();
479     g = BN_new();
480     ctx->dh = DH_new();
481
482     /* select DH group */
483     if (res->selected_dh_group == DH_GROUP_2) {
484         BN_hex2bn(&p, group2);
485         ctx->pubkey_length = DH_GROUP_2_SIZE;
486     } else if (res->selected_dh_group == DH_GROUP_5) {
487         BN_hex2bn(&p, group5);
488         ctx->pubkey_length = DH_GROUP_5_SIZE;
489     } else if (res->selected_dh_group == DH_GROUP_14) {
490         BN_hex2bn(&p, group14);
491         ctx->pubkey_length = DH_GROUP_14_SIZE;
492     } else {
493         LOG(LOG_ERR, "Bad DH group 0x%x\n", res->selected_dh_group);
494         return  PTS_DENIED;
495     }
496
497     BN_set_word(g, 2);
498
499     ctx->dh->p = BN_dup(p);
500     ctx->dh->g = BN_dup(g);
501
502     /* DH gen key */
503     rc = DH_generate_key(ctx->dh);
504
505     pub_key = BN_new();
506     BN_bin2bn(res->dh_respondor_public, ctx->pubkey_length, pub_key);
507
508     /* secret */
509     ctx->secret_length = DH_size(ctx->dh);
510
511     /* malloc */
512     ctx->secret = xmalloc(ctx->secret_length);
513     if (ctx->secret == NULL) {
514         LOG(LOG_ERR, "no memory");
515         return PTS_FATAL;
516     }
517
518     /* calc key */
519     DH_compute_key(ctx->secret, pub_key, ctx->dh);
520
521     /* initiator nonce */
522     fin->dh_initiator_nonce = xmalloc(fin->nonce_length);
523     if (fin->dh_initiator_nonce == NULL) {
524         LOG(LOG_ERR, "no memory");
525         return PTS_FATAL;
526     }
527
528     /* set random */
529     rc = getRandom(fin->dh_initiator_nonce, fin->nonce_length);
530     if (rc != TSS_SUCCESS) {
531         LOG(LOG_ERR, "get random fail\n");
532         return PTS_INTERNAL_ERROR;
533     }
534
535     /* initiator nonce (local copy) */
536     ctx->initiator_nonce_length = fin->nonce_length;
537     ctx->initiator_nonce = fin->dh_initiator_nonce;
538
539     /* pubkey */
540     fin->dh_initiator_public = xmalloc(DH_size(ctx->dh));
541     if (fin->dh_initiator_public == NULL) {
542         return PTS_INTERNAL_ERROR;
543     }
544     BN_bn2bin(ctx->dh->pub_key, fin->dh_initiator_public);
545
546     ctx->pubkey = fin->dh_initiator_public;
547
548     /* calc ExternalDataValue */
549     calcExternalDataValue(ctx);
550
551     /* free */
552     BN_free(p);
553     BN_free(g);
554     BN_free(pub_key);
555
556     return PTS_SUCCESS;
557 }
558
559 /**
560  * Respondor
561  */
562 int calcDhFin(OPENPTS_NONCE *ctx) {
563     BIGNUM *pub_key;
564     PTS_IF_M_DH_Nonce_Finish *fin;
565
566     /* check */
567     if (ctx == NULL) {
568         LOG(LOG_ERR, "null input");
569         return PTS_FATAL;
570     }
571     fin = ctx->fin;
572     if (fin == NULL) {
573         LOG(LOG_ERR, "null input");
574         return PTS_FATAL;
575     }
576
577     /* initiator nonce */
578     ctx->initiator_nonce_length = fin->nonce_length;
579     ctx->initiator_nonce = fin->dh_initiator_nonce;
580
581     /* initiator pubkey */
582     pub_key = BN_new();
583     BN_bin2bn(fin->dh_initiator_public, ctx->pubkey_length, pub_key);
584
585     /* calc secret */
586     ctx->secret_length = DH_size(ctx->dh);
587     ctx->secret = xmalloc_assert(ctx->secret_length);
588     DH_compute_key(ctx->secret, pub_key, ctx->dh);
589
590     /* calc ExternalDataValue */
591     calcExternalDataValue(ctx);
592
593     /* free */
594     BN_free(pub_key);
595     // DH_free(ctx->dh);
596
597     return PTS_SUCCESS;
598 }