2 * This file is part of the OpenPTS project.
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.
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)
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.
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.
26 * \brief calc D-H nonce
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2011-01-22 SM
31 * PTS IF-M DH-Nonce protocol
33 * D-H Nonce Parameters Request
37 * D-H Nonce Parameters Responce
42 * D-H Responder Public Value
46 * Selected Hash Algorithm
47 * D-H Initiater Public Value
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?
54 * nonce size 16-255 (8bit)
64 #include <openssl/sha.h>
65 #include <openssl/dh.h>
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
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";
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";
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";
108 * malloc -> free@freeNonceContext()
114 OPENPTS_NONCE *newNonceContext() {
115 OPENPTS_NONCE *ctx = NULL;
117 DEBUG_CAL("newNonceContext\n");
120 ctx = xmalloc(sizeof(OPENPTS_NONCE));
124 memset(ctx, 0, sizeof(OPENPTS_NONCE));
127 ctx->req = (PTS_IF_M_DH_Nonce_Parameters_Request *)xmalloc(sizeof(PTS_IF_M_DH_Nonce_Parameters_Request));
128 if (ctx->req == NULL) {
132 memset(ctx->req, 0, sizeof(PTS_IF_M_DH_Nonce_Parameters_Request));
135 ctx->res = xmalloc(sizeof(PTS_IF_M_DH_Nonce_Parameters_Responce));
136 if (ctx->res == NULL) {
141 memset(ctx->res, 0, sizeof(PTS_IF_M_DH_Nonce_Parameters_Responce));
144 ctx->fin = xmalloc(sizeof(PTS_IF_M_DH_Nonce_Finish));
145 if (ctx->fin == NULL) {
151 memset(ctx->fin, 0, sizeof(PTS_IF_M_DH_Nonce_Finish));
161 * ctx->res->dh_respondor_nonce
162 * ctx->res->dh_respondor_public
164 * ctx->fin->dh_initiator_nonce
165 * ctx->fin->dh_initiator_public
170 int freeNonceContext(OPENPTS_NONCE *ctx) {
171 DEBUG_CAL("freeNonceContext\n");
174 if (ctx->req != NULL) {
178 if (ctx->res != NULL) {
179 if (ctx->res->dh_respondor_nonce != NULL) {
180 xfree(ctx->res->dh_respondor_nonce);
182 if (ctx->res->dh_respondor_public != NULL) {
183 xfree(ctx->res->dh_respondor_public);
188 if (ctx->fin != NULL) {
189 if (ctx->fin->dh_initiator_nonce != NULL) {
190 xfree(ctx->fin->dh_initiator_nonce);
192 if (ctx->fin->dh_initiator_public != NULL) {
193 xfree(ctx->fin->dh_initiator_public);
198 if (ctx->secret != NULL) {
199 memset(ctx->secret, 0, ctx->secret_length);
203 if (ctx->nonce != NULL) {
208 if (ctx->dh != NULL) {
218 * Calc ExternalDataValue (=nonce)
220 * nonce = HASH("1" | initiator's nonce | respondor's nonce | secret)
222 int calcExternalDataValue(OPENPTS_NONCE *ctx) {
226 // DEBUG("calcExternalDataValue\n");
228 ctx->nonce_length = SHA1_DIGEST_SIZE;
229 ctx->nonce = xmalloc_assert(SHA1_DIGEST_SIZE);
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);
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");
253 * malloc -> free@freeNonceContext()
254 * res->dh_respondor_nonce
255 * res->dh_respondor_public
257 int getDhResponce(OPENPTS_NONCE *ctx) {
260 PTS_IF_M_DH_Nonce_Parameters_Request *req = ctx->req;
261 PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
263 // DEBUG("getDhResponce at Respondor\n");
266 if (req->reserved != 0) {
267 ERROR("reserved must be 0\n");
271 /* select nonce size */
272 if (req->min_nonce_len > 20) {
273 ctx->nonce_length = req->min_nonce_len;
275 ctx->nonce_length = 20;
277 res->nonce_length = ctx->nonce_length;
279 /* set DH Hash Alg */
280 res->hash_alg_set = DH_HASH_SHA1;
281 ctx->selected_hash_alg = DH_HASH_SHA1;
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);
305 res->selected_dh_group = 0;
312 ctx->dh->p = BN_dup(p);
313 ctx->dh->g = BN_dup(g);
316 rc = DH_generate_key(ctx->dh);
318 /* respondor nonce */
321 res->dh_respondor_nonce = xmalloc(res->nonce_length);
322 if (res->dh_respondor_nonce == NULL) {
323 return PTS_INTERNAL_ERROR;
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;
333 /* respondor nonce (local copy)*/
334 ctx->respondor_nonce_length = res->nonce_length;
335 ctx->respondor_nonce = res->dh_respondor_nonce;
340 res->dh_respondor_public = xmalloc(DH_size(ctx->dh));
341 if (res->dh_respondor_public == NULL) {
342 return PTS_INTERNAL_ERROR;
346 BN_bn2bin(ctx->dh->pub_key, res->dh_respondor_public);
347 ctx->pubkey = res->dh_respondor_public;
350 res->reserved[0] = 0;
351 res->reserved[1] = 0;
352 res->reserved[2] = 0;
365 int setDhPubkeylength(OPENPTS_NONCE *ctx) {
366 PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
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;
376 ERROR("Bad DH group\n");
387 * malloc -> free@freeNonceContext()
388 * fin->dh_initiator_nonce
389 * fin->dh_initiator_public
392 int calcDh(OPENPTS_NONCE *ctx) {
396 PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
397 PTS_IF_M_DH_Nonce_Finish *fin = ctx->fin;
400 if (res->reserved[0] != 0) {
401 // TODO check 1,2 too
402 ERROR("reserved must be 0\n");
406 /* set DH Hash Alg */
407 if (res->hash_alg_set & DH_HASH_SHA1) {
409 fin->selected_hash_alg = DH_HASH_SHA1;
410 ctx->selected_hash_alg = DH_HASH_SHA1;
412 ERROR("Bad DH hash\n");
416 /* store respondor nonce */
417 ctx->respondor_nonce_length = res->nonce_length;
418 ctx->respondor_nonce = res->dh_respondor_nonce;
420 /* select initiator nonce size */
421 ctx->nonce_length = res->nonce_length; // same length
422 fin->nonce_length = ctx->nonce_length;
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;
440 ERROR("Bad DH group\n");
446 ctx->dh->p = BN_dup(p);
447 ctx->dh->g = BN_dup(g);
450 rc = DH_generate_key(ctx->dh);
453 BN_bin2bn(res->dh_respondor_public, ctx->pubkey_length, pub_key);
456 ctx->secret_length = DH_size(ctx->dh);
459 ctx->secret = xmalloc(ctx->secret_length);
460 if (ctx->secret == NULL) {
461 return PTS_INTERNAL_ERROR;
465 DH_compute_key(ctx->secret, pub_key, ctx->dh);
467 /* initiator nonce */
468 fin->dh_initiator_nonce = xmalloc(fin->nonce_length);
469 if (fin->dh_initiator_nonce == NULL) {
470 return PTS_INTERNAL_ERROR;
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;
480 /* initiator nonce (local copy) */
481 ctx->initiator_nonce_length = fin->nonce_length;
482 ctx->initiator_nonce = fin->dh_initiator_nonce;
485 fin->dh_initiator_public = xmalloc(DH_size(ctx->dh));
486 if (fin->dh_initiator_public == NULL) {
487 return PTS_INTERNAL_ERROR;
489 BN_bn2bin(ctx->dh->pub_key, fin->dh_initiator_public);
491 ctx->pubkey = fin->dh_initiator_public;
493 /* calc ExternalDataValue */
494 calcExternalDataValue(ctx);
507 int calcDhFin(OPENPTS_NONCE *ctx) {
509 PTS_IF_M_DH_Nonce_Finish *fin = ctx->fin;
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");
515 /* initiator nonce */
516 ctx->initiator_nonce_length = fin->nonce_length;
517 ctx->initiator_nonce = fin->dh_initiator_nonce;
519 /* initiator pubkey */
521 BN_bin2bn(fin->dh_initiator_public, ctx->pubkey_length, pub_key);
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);
528 /* calc ExternalDataValue */
529 calcExternalDataValue(ctx);