OSDN Git Service

a515a0558f33ec91a05e7fe78d4a5007da4df776
[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 2011-01-22 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     // DEBUG("calcExternalDataValue\n");
237     /* check */
238     if (ctx == NULL) {
239         LOG(LOG_ERR, "null input");
240         return PTS_FATAL;
241     }
242
243     ctx->nonce_length = SHA1_DIGEST_SIZE;
244     ctx->nonce = xmalloc_assert(SHA1_DIGEST_SIZE);
245     if (ctx->nonce == NULL) {
246         LOG(LOG_ERR, "no memory");
247         return PTS_FATAL;
248     }
249
250     SHA1_Init(&sha_ctx);
251     SHA1_Update(&sha_ctx, &c, 1);
252     SHA1_Update(&sha_ctx, ctx->initiator_nonce, ctx->initiator_nonce_length);
253     SHA1_Update(&sha_ctx, ctx->respondor_nonce, ctx->respondor_nonce_length);
254     SHA1_Update(&sha_ctx, ctx->secret, ctx->secret_length);
255     SHA1_Final(ctx->nonce, &sha_ctx);
256
257     if (isDebugFlagSet(DEBUG_FLAG)) {
258         LOG(LOG_TODO, "calcExternalDataValue - nonce\n");
259         debugHex("\t\tinitiator_nonce:", ctx->initiator_nonce, ctx->initiator_nonce_length, "\n");
260         debugHex("\t\trespondor_nonce:", ctx->respondor_nonce, ctx->respondor_nonce_length, "\n");
261         debugHex("\t\tsecret         :", ctx->secret, ctx->secret_length, "\n");
262         debugHex("\t\tnonce          :", ctx->nonce, 20, "\n");
263     }
264
265     return PTS_SUCCESS;
266 }
267
268
269 /**
270  * Respondor
271  *
272  * malloc -> free@freeNonceContext()
273  *   res->dh_respondor_nonce
274  *   res->dh_respondor_public
275  */
276 int getDhResponce(OPENPTS_NONCE *ctx) {
277     int rc = 0;
278     BIGNUM *p, *g;
279     PTS_IF_M_DH_Nonce_Parameters_Request  *req;
280     PTS_IF_M_DH_Nonce_Parameters_Responce *res;
281
282     // DEBUG("getDhResponce at Respondor\n");
283
284     /* check */
285     if (ctx == NULL) {
286         LOG(LOG_ERR, "null input");
287         return PTS_FATAL;
288     }
289     req = ctx->req;
290     if (req == NULL) {
291         LOG(LOG_ERR, "null input");
292         return PTS_FATAL;
293     }
294     res = ctx->res;
295     if (res == NULL) {
296         LOG(LOG_ERR, "null input");
297         return PTS_FATAL;
298     }
299     if (req->reserved != 0) {
300         LOG(LOG_ERR, "reserved must be 0\n");
301         return PTS_INTERNAL_ERROR;
302     }
303
304     /* select nonce size */
305     if (req->min_nonce_len > 20) {
306         ctx->nonce_length = req->min_nonce_len;
307     } else {
308         ctx->nonce_length = 20;
309     }
310     res->nonce_length = ctx->nonce_length;
311
312     /* set DH Hash Alg */
313     res->hash_alg_set = DH_HASH_SHA1;
314     ctx->selected_hash_alg = DH_HASH_SHA1;
315
316     /* setup DH */
317     p = BN_new();
318     g = BN_new();
319     ctx->dh = DH_new();
320
321     /* select DH group */
322     if (req->dh_group_set & DH_GROUP_2) {
323         res->selected_dh_group = DH_GROUP_2;
324         ctx->selected_dh_group = DH_GROUP_2;
325         ctx->pubkey_length = DH_GROUP_2_SIZE;
326         BN_hex2bn(&p, group2);
327     } else if (req->dh_group_set & DH_GROUP_5) {
328         res->selected_dh_group = DH_GROUP_5;
329         ctx->selected_dh_group = DH_GROUP_5;
330         ctx->pubkey_length = DH_GROUP_5_SIZE;
331         BN_hex2bn(&p, group5);
332     } else if (req->dh_group_set & DH_GROUP_14) {
333         res->selected_dh_group = DH_GROUP_14;
334         ctx->selected_dh_group = DH_GROUP_14;
335         ctx->pubkey_length = DH_GROUP_14_SIZE;
336         BN_hex2bn(&p, group14);
337     } else {
338         res->selected_dh_group = 0;
339         LOG(LOG_ERR, "Unknown DH group set 0x%x", req->dh_group_set);
340         return PTS_DENIED;
341     }
342
343     BN_set_word(g, 2);
344
345     ctx->dh->p = BN_dup(p);
346     ctx->dh->g = BN_dup(g);
347
348     /* DH gen key */
349     rc = DH_generate_key(ctx->dh);
350
351     /* respondor nonce */
352
353     /* malloc */
354     res->dh_respondor_nonce = xmalloc(res->nonce_length);
355     if (res->dh_respondor_nonce == NULL) {
356         LOG(LOG_ERR, "dh_respondor_nonce is null");
357         return PTS_INTERNAL_ERROR;
358     }
359
360     /* set random */
361     rc = getRandom(res->dh_respondor_nonce, res->nonce_length);
362     if (rc != TSS_SUCCESS) {
363         LOG(LOG_ERR, "get random fail\n");
364         return PTS_INTERNAL_ERROR;
365     }
366
367     /* respondor nonce (local copy)*/
368     ctx->respondor_nonce_length = res->nonce_length;
369     ctx->respondor_nonce = res->dh_respondor_nonce;
370
371     /* pubkey */
372
373     /* malloc */
374     res->dh_respondor_public = xmalloc(DH_size(ctx->dh));
375     if (res->dh_respondor_public == NULL) {
376         LOG(LOG_ERR, "no memory");
377         return PTS_FATAL;
378     }
379
380     /* set */
381     BN_bn2bin(ctx->dh->pub_key, res->dh_respondor_public);
382     ctx->pubkey = res->dh_respondor_public;
383
384     /* reserved */
385     res->reserved[0] = 0;
386     res->reserved[1] = 0;
387     res->reserved[2] = 0;
388
389     /* free */
390     BN_free(p);
391     BN_free(g);
392     // DH_free(ctx->dh);
393
394     return PTS_SUCCESS;
395 }
396
397 /**
398  *
399  */
400 int setDhPubkeylength(OPENPTS_NONCE *ctx) {
401     PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
402
403     /* check */
404     if (ctx == NULL) {
405         LOG(LOG_ERR, "null input");
406         return PTS_FATAL;
407     }
408
409     /* select DH group */
410     if (res->selected_dh_group == DH_GROUP_2) {
411         ctx->pubkey_length = DH_GROUP_2_SIZE;
412     } else if (res->selected_dh_group == DH_GROUP_5) {
413         ctx->pubkey_length = DH_GROUP_5_SIZE;
414     } else if (res->selected_dh_group == DH_GROUP_14) {
415         ctx->pubkey_length = DH_GROUP_14_SIZE;
416     } else {
417         LOG(LOG_ERR, "Bad DH group 0x%x\n", res->selected_dh_group);
418         return PTS_DENIED;  // TODO
419     }
420
421     return PTS_SUCCESS;
422 }
423
424
425 /**
426  * Initiator
427  *
428  * malloc -> free@freeNonceContext()
429  *   fin->dh_initiator_nonce
430  *   fin->dh_initiator_public 
431  *   ctx->secret
432  */
433 int calcDh(OPENPTS_NONCE *ctx) {
434     int rc = 0;
435     BIGNUM *p, *g;
436     BIGNUM *pub_key;
437     PTS_IF_M_DH_Nonce_Parameters_Responce *res;
438     PTS_IF_M_DH_Nonce_Finish *fin;
439
440     /* check */
441     if (ctx == NULL) {
442         LOG(LOG_ERR, "null input");
443         return PTS_FATAL;
444     }
445     res = ctx->res;
446     if (res == NULL) {
447         LOG(LOG_ERR, "null input");
448         return PTS_FATAL;
449     }
450     fin = ctx->fin;
451     if (fin == NULL) {
452         LOG(LOG_ERR, "null input");
453         return PTS_FATAL;
454     }
455
456     if (res->reserved[0] != 0) {
457         // TODO check 1,2 too
458         LOG(LOG_ERR, "reserved must be 0\n");
459         return PTS_INTERNAL_ERROR;
460     }
461
462     /* set DH Hash Alg */
463     if (res->hash_alg_set & DH_HASH_SHA1) {
464         // OK
465         fin->selected_hash_alg = DH_HASH_SHA1;
466         ctx->selected_hash_alg = DH_HASH_SHA1;
467     } else {
468         LOG(LOG_ERR, "Bad DH hash set 0x%x\n", res->hash_alg_set);
469         return PTS_DENIED;
470     }
471
472     /* store respondor nonce */
473     ctx->respondor_nonce_length = res->nonce_length;
474     ctx->respondor_nonce = res->dh_respondor_nonce;
475
476     /* select initiator nonce size */
477     ctx->nonce_length = res->nonce_length;  // same length
478     fin->nonce_length = ctx->nonce_length;
479
480     /* setup DH */
481     p = BN_new();
482     g = BN_new();
483     ctx->dh = DH_new();
484
485     /* select DH group */
486     if (res->selected_dh_group == DH_GROUP_2) {
487         BN_hex2bn(&p, group2);
488         ctx->pubkey_length = DH_GROUP_2_SIZE;
489     } else if (res->selected_dh_group == DH_GROUP_5) {
490         BN_hex2bn(&p, group5);
491         ctx->pubkey_length = DH_GROUP_5_SIZE;
492     } else if (res->selected_dh_group == DH_GROUP_14) {
493         BN_hex2bn(&p, group14);
494         ctx->pubkey_length = DH_GROUP_14_SIZE;
495     } else {
496         LOG(LOG_ERR, "Bad DH group 0x%x\n", res->selected_dh_group);
497         return  PTS_DENIED;
498     }
499
500     BN_set_word(g, 2);
501
502     ctx->dh->p = BN_dup(p);
503     ctx->dh->g = BN_dup(g);
504
505     /* DH gen key */
506     rc = DH_generate_key(ctx->dh);
507
508     pub_key = BN_new();
509     BN_bin2bn(res->dh_respondor_public, ctx->pubkey_length, pub_key);
510
511     /* secret */
512     ctx->secret_length = DH_size(ctx->dh);
513
514     /* malloc */
515     ctx->secret = xmalloc(ctx->secret_length);
516     if (ctx->secret == NULL) {
517         LOG(LOG_ERR, "no memory");
518         return PTS_FATAL;
519     }
520
521     /* calc key */
522     DH_compute_key(ctx->secret, pub_key, ctx->dh);
523
524     /* initiator nonce */
525     fin->dh_initiator_nonce = xmalloc(fin->nonce_length);
526     if (fin->dh_initiator_nonce == NULL) {
527         LOG(LOG_ERR, "no memory");
528         return PTS_FATAL;
529     }
530
531     /* set random */
532     rc = getRandom(fin->dh_initiator_nonce, fin->nonce_length);
533     if (rc != TSS_SUCCESS) {
534         LOG(LOG_ERR, "get random fail\n");
535         return PTS_INTERNAL_ERROR;
536     }
537
538     /* initiator nonce (local copy) */
539     ctx->initiator_nonce_length = fin->nonce_length;
540     ctx->initiator_nonce = fin->dh_initiator_nonce;
541
542     /* pubkey */
543     fin->dh_initiator_public = xmalloc(DH_size(ctx->dh));
544     if (fin->dh_initiator_public == NULL) {
545         return PTS_INTERNAL_ERROR;
546     }
547     BN_bn2bin(ctx->dh->pub_key, fin->dh_initiator_public);
548
549     ctx->pubkey = fin->dh_initiator_public;
550
551     /* calc ExternalDataValue */
552     calcExternalDataValue(ctx);
553
554     /* free */
555     BN_free(p);
556     BN_free(g);
557     BN_free(pub_key);
558
559     return PTS_SUCCESS;
560 }
561
562 /**
563  * Respondor
564  */
565 int calcDhFin(OPENPTS_NONCE *ctx) {
566     BIGNUM *pub_key;
567     PTS_IF_M_DH_Nonce_Finish *fin;
568
569     // DEBUG("calcDhFin at Respondor\n");
570     // printHex("fin->dh_initiator_nonce :",fin->dh_initiator_nonce,fin->nonce_length,"\n");
571     // printHex("fin->dh_initiator_public:",fin->dh_initiator_public,ctx->pubkey_length,"\n");
572
573     /* check */
574     if (ctx == NULL) {
575         LOG(LOG_ERR, "null input");
576         return PTS_FATAL;
577     }
578     fin = ctx->fin;
579     if (fin == NULL) {
580         LOG(LOG_ERR, "null input");
581         return PTS_FATAL;
582     }
583
584     /* initiator nonce */
585     ctx->initiator_nonce_length = fin->nonce_length;
586     ctx->initiator_nonce = fin->dh_initiator_nonce;
587
588     /* initiator pubkey */
589     pub_key = BN_new();
590     BN_bin2bn(fin->dh_initiator_public, ctx->pubkey_length, pub_key);
591
592     /* calc secret */
593     ctx->secret_length = DH_size(ctx->dh);
594     ctx->secret = xmalloc_assert(ctx->secret_length);
595     DH_compute_key(ctx->secret, pub_key, ctx->dh);
596
597     /* calc ExternalDataValue */
598     calcExternalDataValue(ctx);
599
600     /* free */
601     BN_free(pub_key);
602     // DH_free(ctx->dh);
603
604     return PTS_SUCCESS;
605 }