OSDN Git Service

aix feeadback
[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         return NULL;
123     }
124     memset(ctx, 0, sizeof(OPENPTS_NONCE));
125
126     /* malloc req */
127     ctx->req = (PTS_IF_M_DH_Nonce_Parameters_Request *)xmalloc(sizeof(PTS_IF_M_DH_Nonce_Parameters_Request));
128     if (ctx->req == NULL) {
129         xfree(ctx);
130         return NULL;
131     }
132     memset(ctx->req, 0, sizeof(PTS_IF_M_DH_Nonce_Parameters_Request));
133
134     /* malloc res */
135     ctx->res = xmalloc(sizeof(PTS_IF_M_DH_Nonce_Parameters_Responce));
136     if (ctx->res == NULL) {
137         xfree(ctx->req);
138         xfree(ctx);
139         return NULL;
140     }
141     memset(ctx->res, 0, sizeof(PTS_IF_M_DH_Nonce_Parameters_Responce));
142
143     /* malloc fin */
144     ctx->fin = xmalloc(sizeof(PTS_IF_M_DH_Nonce_Finish));
145     if (ctx->fin == NULL) {
146         xfree(ctx->req);
147         xfree(ctx->res);
148         xfree(ctx);
149         return NULL;
150     }
151     memset(ctx->fin, 0, sizeof(PTS_IF_M_DH_Nonce_Finish));
152
153     return ctx;
154 }
155
156 /**
157  * Free OPENPTS_NONCE
158  *
159  * free
160  *   ctx->req
161  *   ctx->res->dh_respondor_nonce
162  *   ctx->res->dh_respondor_public
163  *   ctx->res
164  *   ctx->fin->dh_initiator_nonce
165  *   ctx->fin->dh_initiator_public
166  *   ctx->fin
167  *   ctx->secret
168  *   ctx->nonce
169  */
170 int freeNonceContext(OPENPTS_NONCE *ctx) {
171     DEBUG_CAL("freeNonceContext\n");
172
173     /* free req */
174     if (ctx->req != NULL) {
175         xfree(ctx->req);
176     }
177     /* free res */
178     if (ctx->res != NULL) {
179         if (ctx->res->dh_respondor_nonce != NULL) {
180             xfree(ctx->res->dh_respondor_nonce);
181         }
182         if (ctx->res->dh_respondor_public != NULL) {
183             xfree(ctx->res->dh_respondor_public);
184         }
185         xfree(ctx->res);
186     }
187     /* free fin */
188     if (ctx->fin != NULL) {
189         if (ctx->fin->dh_initiator_nonce != NULL) {
190             xfree(ctx->fin->dh_initiator_nonce);
191         }
192         if (ctx->fin->dh_initiator_public != NULL) {
193             xfree(ctx->fin->dh_initiator_public);
194         }
195         xfree(ctx->fin);
196     }
197     /* free secret */
198     if (ctx->secret != NULL) {
199         memset(ctx->secret, 0, ctx->secret_length);
200         xfree(ctx->secret);
201     }
202     /* free nonce */
203     if (ctx->nonce != NULL) {
204         xfree(ctx->nonce);
205     }
206
207     /* free DH */
208     if (ctx->dh != NULL) {
209         DH_free(ctx->dh);
210     }
211
212     xfree(ctx);
213
214     return PTS_SUCCESS;
215 }
216
217 /**
218  * Calc ExternalDataValue (=nonce)
219  *
220  *  nonce = HASH("1" | initiator's nonce | respondor's nonce | secret)
221  */
222 int calcExternalDataValue(OPENPTS_NONCE *ctx) {
223     SHA_CTX sha_ctx;
224     char c = '1';
225
226     // DEBUG("calcExternalDataValue\n");
227
228     ctx->nonce_length = SHA1_DIGEST_SIZE;
229     ctx->nonce = xmalloc_assert(SHA1_DIGEST_SIZE);
230
231     SHA1_Init(&sha_ctx);
232     SHA1_Update(&sha_ctx, &c, 1);
233     SHA1_Update(&sha_ctx, ctx->initiator_nonce, ctx->initiator_nonce_length);
234     SHA1_Update(&sha_ctx, ctx->respondor_nonce, ctx->respondor_nonce_length);
235     SHA1_Update(&sha_ctx, ctx->secret, ctx->secret_length);
236     SHA1_Final(ctx->nonce, &sha_ctx);
237
238     if (isDebugFlagSet(DEBUG_FLAG)) {
239         TODO("calcExternalDataValue - nonce\n");
240         debugHex("\t\tinitiator_nonce:", ctx->initiator_nonce, ctx->initiator_nonce_length, "\n");
241         debugHex("\t\trespondor_nonce:", ctx->respondor_nonce, ctx->respondor_nonce_length, "\n");
242         debugHex("\t\tsecret         :", ctx->secret, ctx->secret_length, "\n");
243         debugHex("\t\tnonce          :", ctx->nonce, 20, "\n");
244     }
245
246     return PTS_SUCCESS;
247 }
248
249
250 /**
251  * Respondor
252  *
253  * malloc -> free@freeNonceContext()
254  *   res->dh_respondor_nonce
255  *   res->dh_respondor_public
256  */
257 int getDhResponce(OPENPTS_NONCE *ctx) {
258     int rc = 0;
259     BIGNUM *p, *g;
260     PTS_IF_M_DH_Nonce_Parameters_Request  *req = ctx->req;
261     PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
262
263     // DEBUG("getDhResponce at Respondor\n");
264
265     /* check */
266     if (req->reserved != 0) {
267         ERROR("reserved must be 0\n");
268         return -1;
269     }
270
271     /* select nonce size */
272     if (req->min_nonce_len > 20) {
273         ctx->nonce_length = req->min_nonce_len;
274     } else {
275         ctx->nonce_length = 20;
276     }
277     res->nonce_length = ctx->nonce_length;
278
279     /* set DH Hash Alg */
280     res->hash_alg_set = DH_HASH_SHA1;
281     ctx->selected_hash_alg = DH_HASH_SHA1;
282
283     /* setup DH */
284     p = BN_new();
285     g = BN_new();
286     ctx->dh = DH_new();
287
288     /* select DH group */
289     if (req->dh_group_set & DH_GROUP_2) {
290         res->selected_dh_group = DH_GROUP_2;
291         ctx->selected_dh_group = DH_GROUP_2;
292         ctx->pubkey_length = DH_GROUP_2_SIZE;
293         BN_hex2bn(&p, group2);
294     } else if (req->dh_group_set & DH_GROUP_5) {
295         res->selected_dh_group = DH_GROUP_5;
296         ctx->selected_dh_group = DH_GROUP_5;
297         ctx->pubkey_length = DH_GROUP_5_SIZE;
298         BN_hex2bn(&p, group5);
299     } else if (req->dh_group_set & DH_GROUP_14) {
300         res->selected_dh_group = DH_GROUP_14;
301         ctx->selected_dh_group = DH_GROUP_14;
302         ctx->pubkey_length = DH_GROUP_14_SIZE;
303         BN_hex2bn(&p, group14);
304     } else {
305         res->selected_dh_group = 0;
306         ERROR("");
307         return -1;
308     }
309
310     BN_set_word(g, 2);
311
312     ctx->dh->p = BN_dup(p);
313     ctx->dh->g = BN_dup(g);
314
315     /* DH gen key */
316     rc = DH_generate_key(ctx->dh);
317
318     /* respondor nonce */
319
320     /* malloc */
321     res->dh_respondor_nonce = xmalloc(res->nonce_length);
322     if (res->dh_respondor_nonce == NULL) {
323         return PTS_INTERNAL_ERROR;
324     }
325
326     /* set random */
327     rc = getRandom(res->dh_respondor_nonce, res->nonce_length);
328     if (rc != TSS_SUCCESS) {
329         ERROR("get random fail\n");
330         return PTS_INTERNAL_ERROR;
331     }
332
333     /* respondor nonce (local copy)*/
334     ctx->respondor_nonce_length = res->nonce_length;
335     ctx->respondor_nonce = res->dh_respondor_nonce;
336
337     /* pubkey */
338
339     /* malloc */
340     res->dh_respondor_public = xmalloc(DH_size(ctx->dh));
341     if (res->dh_respondor_public == NULL) {
342         return PTS_INTERNAL_ERROR;
343     }
344
345     /* set */
346     BN_bn2bin(ctx->dh->pub_key, res->dh_respondor_public);
347     ctx->pubkey = res->dh_respondor_public;
348
349     /* reserved */
350     res->reserved[0] = 0;
351     res->reserved[1] = 0;
352     res->reserved[2] = 0;
353
354     /* free */
355     BN_free(p);
356     BN_free(g);
357     // DH_free(ctx->dh);
358
359     return PTS_SUCCESS;
360 }
361
362 /**
363  *
364  */
365 int setDhPubkeylength(OPENPTS_NONCE *ctx) {
366     PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
367
368     /* select DH group */
369     if (res->selected_dh_group == DH_GROUP_2) {
370         ctx->pubkey_length = DH_GROUP_2_SIZE;
371     } else if (res->selected_dh_group == DH_GROUP_5) {
372         ctx->pubkey_length = DH_GROUP_5_SIZE;
373     } else if (res->selected_dh_group == DH_GROUP_14) {
374         ctx->pubkey_length = DH_GROUP_14_SIZE;
375     } else {
376         ERROR("Bad DH group\n");
377         return -1;
378     }
379
380     return PTS_SUCCESS;
381 }
382
383
384 /**
385  * Initiator
386  *
387  * malloc -> free@freeNonceContext()
388  *   fin->dh_initiator_nonce
389  *   fin->dh_initiator_public 
390  *   ctx->secret
391  */
392 int calcDh(OPENPTS_NONCE *ctx) {
393     int rc = 0;
394     BIGNUM *p, *g;
395     BIGNUM *pub_key;
396     PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
397     PTS_IF_M_DH_Nonce_Finish *fin = ctx->fin;
398
399     /* check */
400     if (res->reserved[0] != 0) {
401         // TODO check 1,2 too
402         ERROR("reserved must be 0\n");
403         return -1;
404     }
405
406     /* set DH Hash Alg */
407     if (res->hash_alg_set & DH_HASH_SHA1) {
408         // OK
409         fin->selected_hash_alg = DH_HASH_SHA1;
410         ctx->selected_hash_alg = DH_HASH_SHA1;
411     } else {
412         ERROR("Bad DH hash\n");
413         return -1;
414     }
415
416     /* store respondor nonce */
417     ctx->respondor_nonce_length = res->nonce_length;
418     ctx->respondor_nonce = res->dh_respondor_nonce;
419
420     /* select initiator nonce size */
421     ctx->nonce_length = res->nonce_length;  // same length
422     fin->nonce_length = ctx->nonce_length;
423
424     /* setup DH */
425     p = BN_new();
426     g = BN_new();
427     ctx->dh = DH_new();
428
429     /* select DH group */
430     if (res->selected_dh_group == DH_GROUP_2) {
431         BN_hex2bn(&p, group2);
432         ctx->pubkey_length = DH_GROUP_2_SIZE;
433     } else if (res->selected_dh_group == DH_GROUP_5) {
434         BN_hex2bn(&p, group5);
435         ctx->pubkey_length = DH_GROUP_5_SIZE;
436     } else if (res->selected_dh_group == DH_GROUP_14) {
437         BN_hex2bn(&p, group14);
438         ctx->pubkey_length = DH_GROUP_14_SIZE;
439     } else {
440         ERROR("Bad DH group\n");
441         return -1;
442     }
443
444     BN_set_word(g, 2);
445
446     ctx->dh->p = BN_dup(p);
447     ctx->dh->g = BN_dup(g);
448
449     /* DH gen key */
450     rc = DH_generate_key(ctx->dh);
451
452     pub_key = BN_new();
453     BN_bin2bn(res->dh_respondor_public, ctx->pubkey_length, pub_key);
454
455     /* secret */
456     ctx->secret_length = DH_size(ctx->dh);
457
458     /* malloc */
459     ctx->secret = xmalloc(ctx->secret_length);
460     if (ctx->secret == NULL) {
461         return PTS_INTERNAL_ERROR;
462     }
463
464     /* calc key */
465     DH_compute_key(ctx->secret, pub_key, ctx->dh);
466
467     /* initiator nonce */
468     fin->dh_initiator_nonce = xmalloc(fin->nonce_length);
469     if (fin->dh_initiator_nonce == NULL) {
470         return PTS_INTERNAL_ERROR;
471     }
472
473     /* set random */
474     rc = getRandom(fin->dh_initiator_nonce, fin->nonce_length);
475     if (rc != TSS_SUCCESS) {
476         ERROR("get random fail\n");
477         return PTS_INTERNAL_ERROR;
478     }
479
480     /* initiator nonce (local copy) */
481     ctx->initiator_nonce_length = fin->nonce_length;
482     ctx->initiator_nonce = fin->dh_initiator_nonce;
483
484     /* pubkey */
485     fin->dh_initiator_public = xmalloc(DH_size(ctx->dh));
486     if (fin->dh_initiator_public == NULL) {
487         return PTS_INTERNAL_ERROR;
488     }
489     BN_bn2bin(ctx->dh->pub_key, fin->dh_initiator_public);
490
491     ctx->pubkey = fin->dh_initiator_public;
492
493     /* calc ExternalDataValue */
494     calcExternalDataValue(ctx);
495
496     /* free */
497     BN_free(p);
498     BN_free(g);
499     BN_free(pub_key);
500
501     return PTS_SUCCESS;
502 }
503
504 /**
505  * Respondor
506  */
507 int calcDhFin(OPENPTS_NONCE *ctx) {
508     BIGNUM *pub_key;
509     PTS_IF_M_DH_Nonce_Finish *fin = ctx->fin;
510
511     // DEBUG("calcDhFin at Respondor\n");
512     // printHex("fin->dh_initiator_nonce :",fin->dh_initiator_nonce,fin->nonce_length,"\n");
513     // printHex("fin->dh_initiator_public:",fin->dh_initiator_public,ctx->pubkey_length,"\n");
514
515     /* initiator nonce */
516     ctx->initiator_nonce_length = fin->nonce_length;
517     ctx->initiator_nonce = fin->dh_initiator_nonce;
518
519     /* initiator pubkey */
520     pub_key = BN_new();
521     BN_bin2bn(fin->dh_initiator_public, ctx->pubkey_length, pub_key);
522
523     /* calc secret */
524     ctx->secret_length = DH_size(ctx->dh);
525     ctx->secret = xmalloc_assert(ctx->secret_length);
526     DH_compute_key(ctx->secret, pub_key, ctx->dh);
527
528     /* calc ExternalDataValue */
529     calcExternalDataValue(ctx);
530
531     /* free */
532     BN_free(pub_key);
533     // DH_free(ctx->dh);
534
535     return PTS_SUCCESS;
536 }