OSDN Git Service

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