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));
122 LOG(LOG_ERR, "no memory");
125 memset(ctx, 0, sizeof(OPENPTS_NONCE));
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");
134 memset(ctx->req, 0, sizeof(PTS_IF_M_DH_Nonce_Parameters_Request));
137 ctx->res = xmalloc(sizeof(PTS_IF_M_DH_Nonce_Parameters_Responce));
138 if (ctx->res == NULL) {
139 LOG(LOG_ERR, "no memory");
144 memset(ctx->res, 0, sizeof(PTS_IF_M_DH_Nonce_Parameters_Responce));
147 ctx->fin = xmalloc(sizeof(PTS_IF_M_DH_Nonce_Finish));
148 if (ctx->fin == NULL) {
149 LOG(LOG_ERR, "no memory");
155 memset(ctx->fin, 0, sizeof(PTS_IF_M_DH_Nonce_Finish));
165 * ctx->res->dh_respondor_nonce
166 * ctx->res->dh_respondor_public
168 * ctx->fin->dh_initiator_nonce
169 * ctx->fin->dh_initiator_public
174 int freeNonceContext(OPENPTS_NONCE *ctx) {
175 DEBUG_CAL("freeNonceContext\n");
179 LOG(LOG_ERR, "null input");
184 if (ctx->req != NULL) {
188 if (ctx->res != NULL) {
189 if (ctx->res->dh_respondor_nonce != NULL) {
190 xfree(ctx->res->dh_respondor_nonce);
192 if (ctx->res->dh_respondor_public != NULL) {
193 xfree(ctx->res->dh_respondor_public);
198 if (ctx->fin != NULL) {
199 if (ctx->fin->dh_initiator_nonce != NULL) {
200 xfree(ctx->fin->dh_initiator_nonce);
202 if (ctx->fin->dh_initiator_public != NULL) {
203 xfree(ctx->fin->dh_initiator_public);
208 if (ctx->secret != NULL) {
209 memset(ctx->secret, 0, ctx->secret_length);
213 if (ctx->nonce != NULL) {
218 if (ctx->dh != NULL) {
228 * Calc ExternalDataValue (=nonce)
230 * nonce = HASH("1" | initiator's nonce | respondor's nonce | secret)
232 int calcExternalDataValue(OPENPTS_NONCE *ctx) {
236 // DEBUG("calcExternalDataValue\n");
239 LOG(LOG_ERR, "null input");
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");
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);
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");
272 * malloc -> free@freeNonceContext()
273 * res->dh_respondor_nonce
274 * res->dh_respondor_public
276 int getDhResponce(OPENPTS_NONCE *ctx) {
279 PTS_IF_M_DH_Nonce_Parameters_Request *req;
280 PTS_IF_M_DH_Nonce_Parameters_Responce *res;
282 // DEBUG("getDhResponce at Respondor\n");
286 LOG(LOG_ERR, "null input");
291 LOG(LOG_ERR, "null input");
296 LOG(LOG_ERR, "null input");
299 if (req->reserved != 0) {
300 LOG(LOG_ERR, "reserved must be 0\n");
301 return PTS_INTERNAL_ERROR;
304 /* select nonce size */
305 if (req->min_nonce_len > 20) {
306 ctx->nonce_length = req->min_nonce_len;
308 ctx->nonce_length = 20;
310 res->nonce_length = ctx->nonce_length;
312 /* set DH Hash Alg */
313 res->hash_alg_set = DH_HASH_SHA1;
314 ctx->selected_hash_alg = DH_HASH_SHA1;
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);
338 res->selected_dh_group = 0;
339 LOG(LOG_ERR, "Unknown DH group set 0x%x", req->dh_group_set);
345 ctx->dh->p = BN_dup(p);
346 ctx->dh->g = BN_dup(g);
349 rc = DH_generate_key(ctx->dh);
351 /* respondor nonce */
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;
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;
367 /* respondor nonce (local copy)*/
368 ctx->respondor_nonce_length = res->nonce_length;
369 ctx->respondor_nonce = res->dh_respondor_nonce;
374 res->dh_respondor_public = xmalloc(DH_size(ctx->dh));
375 if (res->dh_respondor_public == NULL) {
376 LOG(LOG_ERR, "no memory");
381 BN_bn2bin(ctx->dh->pub_key, res->dh_respondor_public);
382 ctx->pubkey = res->dh_respondor_public;
385 res->reserved[0] = 0;
386 res->reserved[1] = 0;
387 res->reserved[2] = 0;
400 int setDhPubkeylength(OPENPTS_NONCE *ctx) {
401 PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
405 LOG(LOG_ERR, "null input");
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;
417 LOG(LOG_ERR, "Bad DH group 0x%x\n", res->selected_dh_group);
418 return PTS_DENIED; // TODO
428 * malloc -> free@freeNonceContext()
429 * fin->dh_initiator_nonce
430 * fin->dh_initiator_public
433 int calcDh(OPENPTS_NONCE *ctx) {
437 PTS_IF_M_DH_Nonce_Parameters_Responce *res;
438 PTS_IF_M_DH_Nonce_Finish *fin;
442 LOG(LOG_ERR, "null input");
447 LOG(LOG_ERR, "null input");
452 LOG(LOG_ERR, "null input");
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;
462 /* set DH Hash Alg */
463 if (res->hash_alg_set & DH_HASH_SHA1) {
465 fin->selected_hash_alg = DH_HASH_SHA1;
466 ctx->selected_hash_alg = DH_HASH_SHA1;
468 LOG(LOG_ERR, "Bad DH hash set 0x%x\n", res->hash_alg_set);
472 /* store respondor nonce */
473 ctx->respondor_nonce_length = res->nonce_length;
474 ctx->respondor_nonce = res->dh_respondor_nonce;
476 /* select initiator nonce size */
477 ctx->nonce_length = res->nonce_length; // same length
478 fin->nonce_length = ctx->nonce_length;
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;
496 LOG(LOG_ERR, "Bad DH group 0x%x\n", res->selected_dh_group);
502 ctx->dh->p = BN_dup(p);
503 ctx->dh->g = BN_dup(g);
506 rc = DH_generate_key(ctx->dh);
509 BN_bin2bn(res->dh_respondor_public, ctx->pubkey_length, pub_key);
512 ctx->secret_length = DH_size(ctx->dh);
515 ctx->secret = xmalloc(ctx->secret_length);
516 if (ctx->secret == NULL) {
517 LOG(LOG_ERR, "no memory");
522 DH_compute_key(ctx->secret, pub_key, ctx->dh);
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");
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;
538 /* initiator nonce (local copy) */
539 ctx->initiator_nonce_length = fin->nonce_length;
540 ctx->initiator_nonce = fin->dh_initiator_nonce;
543 fin->dh_initiator_public = xmalloc(DH_size(ctx->dh));
544 if (fin->dh_initiator_public == NULL) {
545 return PTS_INTERNAL_ERROR;
547 BN_bn2bin(ctx->dh->pub_key, fin->dh_initiator_public);
549 ctx->pubkey = fin->dh_initiator_public;
551 /* calc ExternalDataValue */
552 calcExternalDataValue(ctx);
565 int calcDhFin(OPENPTS_NONCE *ctx) {
567 PTS_IF_M_DH_Nonce_Finish *fin;
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");
575 LOG(LOG_ERR, "null input");
580 LOG(LOG_ERR, "null input");
584 /* initiator nonce */
585 ctx->initiator_nonce_length = fin->nonce_length;
586 ctx->initiator_nonce = fin->dh_initiator_nonce;
588 /* initiator pubkey */
590 BN_bin2bn(fin->dh_initiator_public, ctx->pubkey_length, pub_key);
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);
597 /* calc ExternalDataValue */
598 calcExternalDataValue(ctx);