OSDN Git Service

fixed issue reported by SAT, base64 functions are updated
[openpts/openpts.git] / src / ifm.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/ifm.c
26  * \brief TCG IF-M protocol
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-04-01
29  * cleanup 2011-04-26 SM
30  *
31  * 2011-06-20 SM - do not use sendfile()
32  *  IF-M did not work with endfile.
33  *  So, we allocate the memory for the whole data.
34  *  If platform uses Linux-IMA with HUGE events. this could be a problem.
35  *  
36  */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <netdb.h>
42 #include <errno.h>
43
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <sys/stat.h>
47 #include <netinet/in.h>
48 #include <unistd.h>
49 #include <fcntl.h>
50
51 #ifdef  HAVE_SENDFILE
52 #include <sys/sendfile.h>
53 #endif
54
55 #include <openpts.h>
56
57 // TODO
58 #define MAX_TLV_MESSAGE_LENGTH 5120000
59
60
61 // DEBUG
62 // 2011-02-24 SM make check => pass
63 // 2011-04-01 SM sendfile not work to new ptsc, too fast? <= wrap read/write
64 // 2011-04-07 SM sendfile not work aggain, RIMM_SET
65 #undef HAVE_SENDFILE
66
67 #ifndef HAVE_SENDFILE
68 #define SENDFILE_BUF_SIZE 4096
69
70 // http://linux.die.net/man/2/sendfile
71 // sendfile - transfer data between file descriptors
72 ssize_t my_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) {
73     char buf[SENDFILE_BUF_SIZE];
74     ssize_t read_size;
75     ssize_t write_size;
76     ssize_t sum = 0;
77
78     DEBUG_IFM("my_sendfile(), size=%d ############################\n", count);
79
80     // offset == NULL
81     do {
82         /* set read size */
83         if ((count - sum) > SENDFILE_BUF_SIZE) {
84             read_size = SENDFILE_BUF_SIZE;
85         } else {
86             read_size = count - sum;
87         }
88
89         /* read */
90         read_size = wrapRead(in_fd, buf, read_size);
91         if (read_size < 0) {
92             // sum = -1;
93             break;
94         }
95
96         /* write */
97         write_size = wrapWrite(out_fd, buf, read_size);
98
99         if (write_size < 0) {
100             ERROR("\n");
101             sum = -1;
102             break;
103         }
104         if (write_size != read_size) {
105             ERROR("\n");
106             sum = -1;
107             break;
108         }
109
110         sum += write_size;
111     } while (sum < (ssize_t) count);
112
113     return sum;
114 }
115 #define sendfile my_sendfile
116 #endif  // !HAVE_SENDFILE
117
118 /**
119  * Copy file date to given buffer 
120  */
121 ssize_t copyfile(BYTE *buf, int in_fd, size_t count) {
122     ssize_t read_size;
123     ssize_t ptr = 0;
124
125     DEBUG_IFM("copyfile(), size=%d ############################\n", count);
126
127     // offset == NULL
128     do {
129         /* set read size */
130         if ((count - ptr) > SENDFILE_BUF_SIZE) {
131             read_size = SENDFILE_BUF_SIZE;
132         } else {
133             read_size = count - ptr;
134         }
135
136         /* read */
137         read_size = wrapRead(in_fd, &buf[ptr], read_size);
138         if (read_size < 0) {
139             // sum = -1;
140             break;
141         }
142         ptr += read_size;
143     } while (ptr < (ssize_t) count);
144
145     return ptr;
146 }
147
148 /**
149  * read IF-M PTS message (standalone)
150  *
151  * This just fill the PTS_IF_M_Attribute structure.
152  * The received packet is parsed by in ptscd.c
153  *
154  * TODO 2011-04-04 socket -> STDIN
155  */
156 PTS_IF_M_Attribute *readPtsTlv(int fdin) {
157     int rc;
158     int len;
159     BYTE head[12];
160     int ptr;
161     int rest;
162     PTS_Byte * read_msg = NULL;
163     PTS_IF_M_Attribute *read_tlv = NULL;  // Host Byte Order
164
165     DEBUG_CAL("readPtsTlvFromSock - start\n");
166
167     memset(head, 0, 12);
168
169     /* malloc TLV for read */
170     read_tlv = (PTS_IF_M_Attribute *)malloc(sizeof(PTS_IF_M_Attribute));
171     if (read_tlv == NULL) {
172         ERROR("no memory");
173         return NULL;
174     }
175     memset(read_tlv, 0, sizeof(PTS_IF_M_Attribute));
176
177     /* read IF-M header */
178     rc = wrapRead(fdin, head, 12);
179     if (rc == 0) {
180         ERROR("sock read fail. probably end of the handshake\n");
181         goto error;
182     }
183
184     // copy buf to PTS_IF_M_Attribute (NBO)
185     memcpy(read_tlv, head, 12);
186     // Convert NBO to Host byte order
187     read_tlv->type = ntohl(read_tlv->type);
188     read_tlv->length = ntohl(read_tlv->length);
189
190 #if 0
191     TODO("IF-M type  : 0x%02x%02x%02x%02x (NBO)",
192         head[4], head[5], head[6], head[7]);
193     TODO("IF-M length: 0x%02x%02x%02x%02x (NBO) %d",
194         head[8], head[9], head[10], head[11], read_tlv->length);
195 #endif
196
197     /* check the length */
198     if (read_tlv->length > MAX_TLV_MESSAGE_LENGTH) {
199         ERROR("read_tlv->length = %d (0x%X)> %d\n",
200             read_tlv->length, read_tlv->length, MAX_TLV_MESSAGE_LENGTH);
201         goto error;
202     }
203
204     /* read msg body */
205     rest = read_tlv->length;
206     if (rest > 0) {
207         read_msg = (PTS_Byte *)malloc(rest + 1);
208         if (read_msg == NULL) {
209             ERROR("no memory (size = %d)\n", rest +1);
210             goto error;
211         } else {
212             ptr = 0;
213             while (1) {
214                 len = wrapRead(fdin, &read_msg[ptr], rest);
215                 if (len == 0) {
216                     break;
217                 }
218                 ptr += len;
219                 rest -= len;
220
221                 if (rest < 0) {
222                     break;
223                 }
224                 // TODO check timeout
225             }
226         }
227         read_msg[read_tlv->length] = 0;
228         read_tlv->value = read_msg;
229     } else {
230         read_tlv->value = NULL;
231     }
232
233     /* done */
234     DEBUG_IFM("IF-M read,  type=0x%08x, length=%d\n",
235         read_tlv->type, read_tlv->length);
236     DEBUG_CAL("readPtsTlvFromSock - done\n");
237
238     // NOTE read_tlv->value may contains MBO structure.
239     return read_tlv;
240
241   error:
242     // if (read_msg != NULL) free(read_msg);
243     if (read_tlv != NULL) freePtsTlv(read_tlv);
244     return NULL;
245 }
246
247
248 /**
249  * free PTS_IF_M_Attribute
250  */
251 void freePtsTlv(PTS_IF_M_Attribute *tlv) {
252     if (tlv == NULL) {
253         return;
254     }
255
256     /* free*/
257     if (tlv->value != NULL) {
258         free(tlv->value);
259     }
260     free(tlv);
261 }
262
263
264
265
266
267 /* TNC, libtnc */
268
269 /**
270  *  malloc TLV buffer and fill the header
271  *  return ptr of buffer
272  */
273 BYTE *getTlvBuffer(int type, int length) {
274     BYTE *buf;
275     PTS_IF_M_Attribute *write_tlv;
276
277     if ((buf = malloc(12 + length)) == NULL) {
278         ERROR("no memory");
279         return NULL;
280     }
281     /* setup TLV header */
282     write_tlv = (PTS_IF_M_Attribute *)buf;
283     write_tlv->flags  = 0;
284     write_tlv->vid[0] = (TNC_VENDORID_OPENPTS >> 16) & 0xff;
285     write_tlv->vid[1] = (TNC_VENDORID_OPENPTS >> 8) & 0xff;
286     write_tlv->vid[2] = TNC_VENDORID_OPENPTS & 0xff;
287     write_tlv->type   = htonl(type);
288     write_tlv->length = htonl(length);
289
290     return buf;
291 }
292
293 /**
294  * get IF-M PTS message (TNC)
295  * return *msg (Network Byte Order)
296  * TODO use RC core
297  */
298 BYTE* getPtsTlvMessage(OPENPTS_CONTEXT *ctx, int type, int *len) {
299     int i;
300     OPENPTS_CONFIG *conf;
301     UINT32 length = 0;  // endian of host
302     BYTE * buf;
303     int ptr;
304     int rc;
305     UINT16 nbou16;
306
307     int fsize[MAX_RM_NUM];
308     int fd[MAX_RM_NUM];
309     int count[MAX_RM_NUM];
310     struct stat st[MAX_RM_NUM];
311
312     UINT32 num;
313
314     DEBUG("writePtsTlvToSock - start\n");
315
316     /* check */
317     if (ctx == NULL) {
318         ERROR("ctx is NULL\n");
319         return NULL;
320     }
321     conf = ctx->conf;
322     if (conf == NULL) {
323         ERROR("conf is NULL\n");
324         return NULL;
325     }
326
327     /* init fd[] */
328     for (i = 0; i < MAX_RM_NUM; i++) {
329         fd[i] = -1;
330     }
331
332     /* TLV */
333     *len = 0;
334
335     switch (type) {
336     /* Collector <-- Verifier Simple requests (no value)*/
337     case REQUEST_TPM_PUBKEY:
338     case REQUEST_INTEGRITY_REPORT:
339     case REQUEST_RIMM_SET:
340     case REQUEST_NEW_RIMM_SET:
341     case VERIFICATION_RESULT:  // TODO
342 #ifdef CONFIG_AIDE
343     case REQUEST_AIDE_DATABASE:
344 #endif
345         buf = getTlvBuffer(type, 0);
346         if (buf == NULL) goto error;
347         break;
348
349     /* Collector <-> Verifier */
350     case OPENPTS_CAPABILITIES:
351         length = sizeof(OPENPTS_IF_M_Capability);
352
353         buf = getTlvBuffer(type, length);
354         if (buf == NULL) goto error;
355
356         ptr = 12;
357         /* Send versions */
358         memcpy(&buf[ptr +  0], &ctx->conf->pts_flag, 4);
359         memcpy(&buf[ptr +  4], &ctx->conf->tpm_version, 4);
360         memcpy(&buf[ptr +  8], &ctx->conf->tss_version, 4);
361         memcpy(&buf[ptr + 12], &ctx->conf->pts_version, 4);
362         /* Send Platform UUID, ctx->uuid */
363         memcpy(&buf[ptr + 16], ctx->conf->uuid->uuid, 16);
364
365         /* Send RM UUID */
366         if (ctx->conf->rm_uuid == NULL) {
367             // TODO  verifier does not have Rm UUID. just send Verifier's UUID
368             DEBUG("writePtsTlvToSock() RM uuid is NULL, => send platform UUID\n");
369             memcpy(&buf[ptr + 32], ctx->conf->uuid->uuid, 16);
370         } else if (ctx->conf->rm_uuid->uuid == NULL) {
371             // TODO verifier?
372             DEBUG("writePtsTlvToSock() RM uuid is NULL, => send platform UUID, file = %s\n",
373                 ctx->conf->rm_uuid->filename);
374
375             memcpy(&buf[ptr + 32], ctx->conf->uuid->uuid, 16);
376         } else {
377             memcpy(&buf[ptr + 32], ctx->conf->rm_uuid->uuid, 16);
378         }
379         break;
380
381
382
383     /* Collector --> Verifier */
384     case TPM_PUBKEY:
385         if ((ctx->conf->pubkey != NULL) && (ctx->conf->pubkey_length > 0)) {
386             /* PUB key exist */
387             length = ctx->conf->pubkey_length;
388             buf = getTlvBuffer(type, length);
389             if (buf == NULL) goto error;
390
391             /* copy PUBKEY */
392             memcpy(&buf[12], ctx->conf->pubkey, ctx->conf->pubkey_length);
393
394         } else {
395             /* PUB key is missing */
396             ERROR("writePtsTlvToSock - PUBKEY blob is missing\n");
397             ctx->ifm_errno = PTS_FATAL;
398             ctx->ifm_strerror = smalloc("Piblic key is missing");
399             length = 0;
400             goto error;
401         }
402         break;
403
404     /* Collector --> Verifier */
405     case RIMM_SET:
406         /* open/read RM files */
407         length = 4;  // for RM num
408         for (i = 0; i < conf->rm_num; i++) {
409             /* open */
410             fd[i] = open(ctx->conf->rm_filename[i], O_RDONLY);
411             if (fd[i] < 0) {
412                 // 20101124 SM must be a fullpath for Daemon
413                 ERROR("Can't open RM[%d] files, %s\n",
414                     i, ctx->conf->rm_filename[i]);
415                 /* send Error massage */
416                 ctx->ifm_errno = PTS_FATAL;
417                 ctx->ifm_strerror =
418                     smalloc("Manifest not found, initialize the collector");
419                 goto error;
420             }
421             /* size */
422             fstat(fd[i], &st[i]);
423             fsize[i] = st[i].st_size;
424             length += 4 + fsize[i];
425         }
426         DEBUG_IFM("writePtsTlv - RIMM_SET, length = %d", length);
427
428         buf = getTlvBuffer(type, length);
429         if (buf == NULL) goto error;
430         ptr = 12;
431
432         // NUM of RM
433         num = htonl(conf->rm_num);
434         memcpy(&buf[ptr], (BYTE *)&num, 4);
435         ptr += 4;
436
437         for (i = 0; i< conf->rm_num; i++) {
438             // length of RM[i]
439             num = htonl(fsize[i]);
440             // rc = wrapWrite(fdout, (BYTE *)&num, 4);
441             memcpy(&buf[ptr], (BYTE *)&num, 4);
442             ptr += 4;
443
444             count[i] = copyfile(&buf[ptr], fd[i], fsize[i]);
445             if (count[i] != fsize[i]) {
446                 ERROR("copyfile() faild %d != %d\n", count[i], fsize[i]);
447             }
448
449             /* close */
450             close(fd[i]);
451             fd[i] = -1;
452             ptr += fsize[i];
453             DEBUG_IFM("RM[%d] len = %d\n", i, count[i]);
454         }
455         break;
456
457     /* Collector --> Verifier */
458     case NEW_RIMM_SET:
459         /* check */
460         if (conf->newrm_num == 0) {
461             /* New RM is missing => send Error massage */
462             ctx->ifm_errno = PTS_FATAL;
463             ctx->ifm_strerror = smalloc("New Manifest not found, check the collector");
464             goto error;
465         }
466
467         /* setup TLV header  (2/2) */
468         length = 16 + 4;  // UUID + num
469         for (i = 0; i < conf->newrm_num; i++) {
470             fd[i] = open(ctx->conf->newrm_filename[i], O_RDONLY);
471             if (fd[i] < 0) {
472                 // 20101124 SM must be a fullpath for Daemon
473                 ERROR("Error RM file, %s not found\n", ctx->conf->newrm_filename[i]);
474                 /* send Error massage */
475                 ctx->ifm_errno = PTS_FATAL;
476                 ctx->ifm_strerror =
477                     smalloc("New Manifest file not found, check the collector");
478                 goto error;
479             }
480             /* check the size */
481             fstat(fd[i], &st[i]);
482             fsize[i] = st[i].st_size;
483             length += 4 + fsize[i];
484         }
485
486
487         DEBUG_IFM("writePtsTlv - NEW_RIMM_SET, length = %d", length);
488
489         buf = getTlvBuffer(type, length);
490         if (buf == NULL) goto error;
491         ptr = 12;
492
493
494         // UUID
495         memcpy(&buf[ptr], ctx->conf->newrm_uuid->uuid, 16);
496         ptr += 16;
497
498         // NUM of RM
499         num = htonl(conf->newrm_num);
500         memcpy(&buf[ptr], (BYTE *)&num, 4);
501         ptr += 4;
502
503         for (i = 0; i< conf->newrm_num; i++) {
504             // length of RM[i]
505             num = htonl(fsize[i]);
506             memcpy(&buf[ptr], (BYTE *)&num, 4);
507             ptr += 4;
508             // RM[i] body
509             count[i] = copyfile(&buf[ptr], fd[i], fsize[i]);
510             /* close */
511             close(fd[i]);
512             fd[i] = -1;
513             ptr += fsize[i];
514             DEBUG_IFM("RM[%d] len = %d\n", i, count[i]);
515         }
516         break;
517
518     case NONCE:
519         length = ctx->nonce->nonce_length;
520         buf = getTlvBuffer(type, length);
521         if (buf == NULL) goto error;
522         memcpy(&buf[12], ctx->nonce->nonce, length);
523         break;
524
525     case INTEGRITY_REPORT:
526         /* generate new IR */
527         rc = genIr(ctx);
528         if (rc != PTS_SUCCESS) {
529             ERROR("writePtsTlvToSock - gen IR failed\n");
530             /* send Error massage */
531             ctx->ifm_errno = PTS_FATAL;
532             ctx->ifm_strerror = smalloc("Generation of IR failed");
533             goto error;
534         }
535
536         /* check the IR size */
537         fd[0] = open(ctx->conf->ir_filename, O_RDONLY);  // TODO(munetoh)
538         if (fd[0] < 0) {
539             ERROR("Error %s not found\n", ctx->conf->ir_filename);
540             /* send Error massage */
541             ctx->ifm_errno = PTS_FATAL;
542             ctx->ifm_strerror = smalloc("IR file is missing");
543             goto error;
544         }
545
546         fstat(fd[0], &st[0]);
547         fsize[0] = st[0].st_size;
548         length = fsize[0];
549         /* close */
550         close(fd[0]);
551         fd[0] = -1;
552
553
554         buf = getTlvBuffer(type, length);
555         if (buf == NULL) goto error;
556         ptr = 12;
557
558         fd[0] = open(ctx->conf->ir_filename, O_RDONLY);
559         count[0] = copyfile(&buf[ptr], fd[0], fsize[0]);
560         if (count[0] != fsize[0]) {
561             ERROR("copyfile() faild %d != %d\n", count[0], fsize[0]);
562         }
563
564         /* close */
565         close(fd[0]);
566         fd[0] = -1;
567
568         break;
569
570 #ifdef CONFIG_AIDE
571     case AIDE_DATABASE:  /* AIDE DATABASE: C -> V */
572         /* setup TLV header  (2/2) */
573         /* body */
574         if (ctx->conf->aide_database_filename == NULL) {
575             // Test
576             DEBUG("writePtsTlvToSock - Error AIDE DB file is not configured\n");
577             ctx->ifm_errno = PTS_FATAL;
578             ctx->ifm_strerror = smalloc("AIDE DB file is not configured");
579             goto error;
580         } else {
581             fd[0] = open(ctx->conf->aide_database_filename, O_RDONLY);
582             if (fd[0] < 0) {
583                 /* AIDE file is missing, erorr */
584                 ERROR("writePtsTlvToSock - Error AIDE DB file, %s not found\n",
585                     ctx->conf->aide_database_filename);
586                 /* send Error massage */
587                 ctx->ifm_errno = PTS_FATAL;
588                 ctx->ifm_strerror = smalloc("AIDE file not found");
589                 goto error;
590             } else {
591                 /* OK */
592                 fstat(fd[0], &st[0]);
593                 fsize[0] = st[0].st_size;
594                 length = fsize[0];
595                 /* close */
596                 close(fd[0]);
597                 fd[0] = -1;
598             }
599         }
600
601         buf = getTlvBuffer(type, length);
602         if (buf == NULL) goto error;
603         ptr = 12;
604
605
606         if (length > 0) {
607             // BODY1
608             fd[0] = open(ctx->conf->aide_database_filename, O_RDONLY);
609             count[0] = copyfile(&buf[ptr], fd[0], fsize[0]);
610             if (count[0] != fsize[0]) {
611                 ERROR("copyfile() faild %d != %d\n", count[0], fsize[0]);
612             }
613
614             /* close */
615             close(fd[0]);
616             fd[0] = -1;
617
618             DEBUG_IFM("writePtsTlv - AIDE_DATABASE, file =  %s\n",
619                 ctx->conf->aide_database_filename);
620             // DEBUG_IFM("AIDE DATABASE len = %d\n", count[0]);
621         }
622         DEBUG_IFM("writePtsTlv - AIDE_DATABASE, length = %d", length);
623         break;
624 #endif  // CONFIG_AIDE
625
626
627     case DH_NONCE_PARAMETERS_REQUEST:  /* DH: Initiator -> Respondor */
628         /* setup TLV header  (2/2) */
629         length = 4;
630         buf = getTlvBuffer(type, length);
631         if (buf == NULL) goto error;
632         ptr = 12;
633
634         /* Send DH Nonce */
635         buf[0] = ctx->nonce->req->reserved;
636         buf[1] = ctx->nonce->req->min_nonce_len;
637         memcpy(&buf[ptr], buf, 2);
638         ptr += 2;
639
640         nbou16 = htons(ctx->nonce->req->dh_group_set);
641         memcpy(&buf[ptr], (BYTE *)&nbou16, 2);
642         ptr += 2;
643
644         DEBUG_IFM("writePtsTlv - DH_NONCE_PARAMETERS_REQUEST, length = %d", length);
645         break;
646
647     case DH_NONCE_PARAMETORS_RESPONSE:  /* DH: IRespondor -> Initiator */
648         /* setup TLV header  (2/2) */
649         length =
650             4 + 4 +
651             ctx->nonce->respondor_nonce_length +
652             ctx->nonce->pubkey_length;
653
654         buf = getTlvBuffer(type, length);
655         if (buf == NULL) goto error;
656         ptr = 12;
657
658         /* Send DH param  */
659         buf[0] = ctx->nonce->res->reserved[0];
660         buf[1] = ctx->nonce->res->reserved[1];
661         buf[2] = ctx->nonce->res->reserved[2];
662         buf[3] = ctx->nonce->res->nonce_length;
663         memcpy(&buf[ptr], buf, 4);
664         ptr += 4;
665
666         nbou16 = htons(ctx->nonce->res->selected_dh_group);
667         memcpy(&buf[ptr], (BYTE *)&nbou16, 2);
668         ptr += 2;
669
670         nbou16 = htons(ctx->nonce->res->hash_alg_set);
671         memcpy(&buf[ptr], (BYTE *)&nbou16, 2);
672         ptr += 2;
673
674         /* nonce */
675         memcpy(
676             &buf[ptr],
677             ctx->nonce->respondor_nonce,
678             ctx->nonce->respondor_nonce_length);
679         ptr += ctx->nonce->respondor_nonce_length;
680
681         /* send dh_respondor_public */
682         memcpy(
683             &buf[ptr],
684             ctx->nonce->pubkey,
685             ctx->nonce->pubkey_length);
686         ptr += ctx->nonce->pubkey_length;
687
688         DEBUG_IFM("writePtsTlv - DH_NONCE_PARAMETORS_RESPONSE, length = %d", length);
689         break;
690
691     case DH_NONCE_FINISH: /* DH: Initiator -> Respondor */
692         /* setup TLV header  (2/2) */
693         length =
694             4 +
695             ctx->nonce->initiator_nonce_length +
696             ctx->nonce->pubkey_length;
697
698         buf = getTlvBuffer(type, length);
699         if (buf == NULL) goto error;
700         ptr = 12;
701
702         /* Send IF-M TLV header */
703
704         /* Send */
705         buf[0] = ctx->nonce->fin->reserved = 0;
706         buf[1] = ctx->nonce->fin->nonce_length = ctx->nonce->initiator_nonce_length;
707         memcpy(&buf[ptr], (BYTE *)&buf, 2);
708         ptr += 2;
709
710         nbou16 = htons(ctx->nonce->fin->selected_hash_alg);
711         memcpy(&buf[ptr], (BYTE *)&nbou16, 2);
712         ptr += 2;
713
714         /* send dh_initiator_pubkey */
715         memcpy(&buf[ptr], ctx->nonce->pubkey, ctx->nonce->pubkey_length);
716         ptr += ctx->nonce->pubkey_length;
717
718         /* send dh_initiator_nonce */
719         memcpy(
720             &buf[ptr],
721             ctx->nonce->initiator_nonce,
722             ctx->nonce->initiator_nonce_length);
723         ptr += ctx->nonce->initiator_nonce_length;
724
725         DEBUG_IFM("writePtsTlv - DH_NONCE_FINISH, length = %d", length);
726         break;
727
728
729     case OPENPTS_ERROR:
730         /* setup TLV header  (2/2) */
731         // TODO
732         if (ctx->ifm_strerror != NULL) {
733             length = 4 + 4 + strlen(ctx->ifm_strerror);
734         } else {
735             length = 4 + 4 + 0;
736         }
737
738         buf = getTlvBuffer(type, length);
739         if (buf == NULL) goto error;
740         ptr = 12;
741
742         {
743             UINT32 ifm_errno;
744             UINT32 size = 0;
745             UINT32 len = 0;
746             /* send error code */
747             ifm_errno = htonl(ctx->ifm_errno);
748             memcpy(&buf[ptr], (BYTE *)&ifm_errno, 4);
749             ptr += 4;
750
751             /* send msg num */
752
753             if (ctx->ifm_strerror != NULL) {
754                 len = strlen(ctx->ifm_strerror);
755                 size = htonl(len);
756                 memcpy(&buf[ptr], (BYTE *)&size, 4);
757                 ptr += 4;
758
759                 memcpy(&buf[ptr], (BYTE *)&ctx->ifm_strerror, len);
760                 ptr += len;
761                 /* free */
762                 free(ctx->ifm_strerror);
763             } else {
764                 size = 0;
765                 memcpy(&buf[ptr], (BYTE *)&size, 4);
766                 ptr += 4;
767             }
768         }
769
770         DEBUG_IFM("writePtsTlv - OPENPTS_ERROR, length = %d", length);
771         break;
772
773     default:
774         // BAT type
775         ERROR("BAD IF-M OPENPTS MESSAGE TYPE, type=0x%x\n", type);
776         return NULL;
777     }
778
779     DEBUG_IFM("IF-M message, type=0x%x, length=%d\n",
780         type, length);
781     DEBUG("writePtsTlvToSock - done\n");
782
783     *len = 12 + length;
784     return buf;
785
786   error:
787     /* close files*/
788     for (i = 0; i < MAX_RM_NUM; i++) {
789         if (fd[i] >= 0) close(fd[i]);
790     }
791
792     *len = 0;
793     return NULL;
794 }
795
796 /**
797  * write IF-M PTS message ()
798  *
799  * we are using sendfile() here and send the data steb by step. 
800  * but IF-M of IMC/IMV version need to create whole blob to send.
801  *
802  * v0.2.4 - sendfile() not work with ptsc. use my_sendfile()
803  *
804  * Retrun
805  *  length of write data
806  *  -1 ERROR
807  */
808 int writePtsTlv(OPENPTS_CONTEXT *ctx, int fdout, int type) {
809     int rc = -1;
810     BYTE *message;
811     int length = 0;
812     int len;
813
814     OPENPTS_CONFIG *conf;
815
816     /* check */
817     if (ctx == NULL) {
818         ERROR("ctx is NULL\n");
819         return -1;
820     }
821     conf = ctx->conf;
822     if (conf == NULL) {
823         ERROR("conf is NULL\n");
824         return -1;
825     }
826     if (conf->uuid == NULL) {
827         ERROR("writePtsTlvToSock() - conf->uuid is NULL\n");
828         return -1;
829     }
830
831     DEBUG_CAL("writePtsTlvToSock - start\n");
832
833     message = getPtsTlvMessage(ctx, type, &length);
834     if (message != NULL) {
835         rc = wrapWrite(fdout, message, length);
836         DEBUG_IFM("writePtsTlv - type=%d, length = %d", type, length);
837     } else {
838         goto error;
839     }
840
841     DEBUG_CAL("writePtsTlvToSock - done\n");
842
843     /* done */
844     rc = length;
845     return rc;
846
847   error:
848     ERROR("writePtsTlvToSock()\n");
849
850     /* send ERROR */
851     len = writePtsTlv(ctx, fdout, OPENPTS_ERROR);
852     if (len < 0) {
853         ERROR("send OPENPTS_ERROR was faild");
854     }
855
856     return -1;
857 }
858
859
860