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 2012-01-05 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) {
238 LOG(LOG_ERR, "null input");
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");
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);
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");
271 * malloc -> free@freeNonceContext()
272 * res->dh_respondor_nonce
273 * res->dh_respondor_public
275 int getDhResponce(OPENPTS_NONCE *ctx) {
278 PTS_IF_M_DH_Nonce_Parameters_Request *req;
279 PTS_IF_M_DH_Nonce_Parameters_Responce *res;
283 LOG(LOG_ERR, "null input");
288 LOG(LOG_ERR, "null input");
293 LOG(LOG_ERR, "null input");
296 if (req->reserved != 0) {
297 LOG(LOG_ERR, "reserved must be 0\n");
298 return PTS_INTERNAL_ERROR;
301 /* select nonce size */
302 if (req->min_nonce_len > 20) {
303 ctx->nonce_length = req->min_nonce_len;
305 ctx->nonce_length = 20;
307 res->nonce_length = ctx->nonce_length;
309 /* set DH Hash Alg */
310 res->hash_alg_set = DH_HASH_SHA1;
311 ctx->selected_hash_alg = DH_HASH_SHA1;
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);
335 res->selected_dh_group = 0;
336 LOG(LOG_ERR, "Unknown DH group set 0x%x", req->dh_group_set);
342 ctx->dh->p = BN_dup(p);
343 ctx->dh->g = BN_dup(g);
346 rc = DH_generate_key(ctx->dh);
348 /* respondor nonce */
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;
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;
364 /* respondor nonce (local copy)*/
365 ctx->respondor_nonce_length = res->nonce_length;
366 ctx->respondor_nonce = res->dh_respondor_nonce;
371 res->dh_respondor_public = xmalloc(DH_size(ctx->dh));
372 if (res->dh_respondor_public == NULL) {
373 LOG(LOG_ERR, "no memory");
378 BN_bn2bin(ctx->dh->pub_key, res->dh_respondor_public);
379 ctx->pubkey = res->dh_respondor_public;
382 res->reserved[0] = 0;
383 res->reserved[1] = 0;
384 res->reserved[2] = 0;
397 int setDhPubkeylength(OPENPTS_NONCE *ctx) {
398 PTS_IF_M_DH_Nonce_Parameters_Responce *res = ctx->res;
402 LOG(LOG_ERR, "null input");
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;
414 LOG(LOG_ERR, "Bad DH group 0x%x\n", res->selected_dh_group);
415 return PTS_DENIED; // TODO
425 * malloc -> free@freeNonceContext()
426 * fin->dh_initiator_nonce
427 * fin->dh_initiator_public
430 int calcDh(OPENPTS_NONCE *ctx) {
434 PTS_IF_M_DH_Nonce_Parameters_Responce *res;
435 PTS_IF_M_DH_Nonce_Finish *fin;
439 LOG(LOG_ERR, "null input");
444 LOG(LOG_ERR, "null input");
449 LOG(LOG_ERR, "null input");
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;
459 /* set DH Hash Alg */
460 if (res->hash_alg_set & DH_HASH_SHA1) {
462 fin->selected_hash_alg = DH_HASH_SHA1;
463 ctx->selected_hash_alg = DH_HASH_SHA1;
465 LOG(LOG_ERR, "Bad DH hash set 0x%x\n", res->hash_alg_set);
469 /* store respondor nonce */
470 ctx->respondor_nonce_length = res->nonce_length;
471 ctx->respondor_nonce = res->dh_respondor_nonce;
473 /* select initiator nonce size */
474 ctx->nonce_length = res->nonce_length; // same length
475 fin->nonce_length = ctx->nonce_length;
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;
493 LOG(LOG_ERR, "Bad DH group 0x%x\n", res->selected_dh_group);
499 ctx->dh->p = BN_dup(p);
500 ctx->dh->g = BN_dup(g);
503 rc = DH_generate_key(ctx->dh);
506 BN_bin2bn(res->dh_respondor_public, ctx->pubkey_length, pub_key);
509 ctx->secret_length = DH_size(ctx->dh);
512 ctx->secret = xmalloc(ctx->secret_length);
513 if (ctx->secret == NULL) {
514 LOG(LOG_ERR, "no memory");
519 DH_compute_key(ctx->secret, pub_key, ctx->dh);
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");
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;
535 /* initiator nonce (local copy) */
536 ctx->initiator_nonce_length = fin->nonce_length;
537 ctx->initiator_nonce = fin->dh_initiator_nonce;
540 fin->dh_initiator_public = xmalloc(DH_size(ctx->dh));
541 if (fin->dh_initiator_public == NULL) {
542 return PTS_INTERNAL_ERROR;
544 BN_bn2bin(ctx->dh->pub_key, fin->dh_initiator_public);
546 ctx->pubkey = fin->dh_initiator_public;
548 /* calc ExternalDataValue */
549 calcExternalDataValue(ctx);
562 int calcDhFin(OPENPTS_NONCE *ctx) {
564 PTS_IF_M_DH_Nonce_Finish *fin;
568 LOG(LOG_ERR, "null input");
573 LOG(LOG_ERR, "null input");
577 /* initiator nonce */
578 ctx->initiator_nonce_length = fin->nonce_length;
579 ctx->initiator_nonce = fin->dh_initiator_nonce;
581 /* initiator pubkey */
583 BN_bin2bn(fin->dh_initiator_public, ctx->pubkey_length, pub_key);
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);
590 /* calc ExternalDataValue */
591 calcExternalDataValue(ctx);