OSDN Git Service

cleanup
[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
416     /* Collector --> Verifier */
417     case TPM_PUBKEY:
418     {
419         if ((ctx->conf->pubkey != NULL) && (ctx->conf->pubkey_length > 0)) {
420             /* PUB key exist */
421             length = ctx->conf->pubkey_length;
422             buf = getTlvBuffer(type, length);
423             if (buf == NULL) {
424                 LOG(LOG_ERR, "getTlvBuffer() is null");
425                 goto error;
426             }
427
428             /* copy PUBKEY */
429             memcpy(&buf[12], ctx->conf->pubkey, ctx->conf->pubkey_length);
430
431         } else {
432             /* PUB key is missing */
433             LOG(LOG_ERR, "writePtsTlvToSock - PUBKEY blob is missing\n");
434             ctx->ifm_errno = PTS_FATAL;
435             ctx->ifm_strerror = smalloc_assert("Public key is missing");
436             length = 0;
437             goto error;
438         }
439         break;
440     }
441
442     /* Collector --> Verifier */
443     case RIMM_SET:
444     {
445         /* open/read RM files */
446         length = 4;  // for RM num
447         for (i = 0; i < conf->rm_num; i++) {
448             /* open */
449             fd[i] = open(ctx->conf->rm_filename[i], O_RDONLY);
450             if (fd[i] < 0) {
451                 // 20101124 SM must be a fullpath for Daemon
452                 LOG(LOG_ERR, "Can't open RM[%d] files, %s\n",
453                     i, ctx->conf->rm_filename[i]);
454                 /* send Error massage */
455                 ctx->ifm_errno = PTS_FATAL;
456                 ctx->ifm_strerror =
457                     smalloc_assert("Manifest not found, initialize the collector");
458                 goto error;
459             }
460             /* size */
461             if (-1 == fstat(fd[i], &st[i])) {
462                 LOG(LOG_ERR, "fstat failed with errno %d\n", errno);
463                 goto error;
464             }
465             fsize[i] = st[i].st_size;
466             length += 4 + fsize[i];
467         }
468         DEBUG_IFM("writePtsTlv - RIMM_SET, length = %d", length);
469
470         buf = getTlvBuffer(type, length);
471         if (buf == NULL) goto error;
472         ptr = 12;
473
474         // NUM of RM
475         num = htonl(conf->rm_num);
476         memcpy(&buf[ptr], (BYTE *)&num, 4);
477         ptr += 4;
478
479         for (i = 0; i< conf->rm_num; i++) {
480             // length of RM[i]
481             num = htonl(fsize[i]);
482             // rc = wrapWrite(fdout, (BYTE *)&num, 4);
483             memcpy(&buf[ptr], (BYTE *)&num, 4);
484             ptr += 4;
485
486             count[i] = copyfile(&buf[ptr], fd[i], fsize[i]);
487             if (count[i] != fsize[i]) {
488                 LOG(LOG_ERR, "copyfile() faild %d != %d\n", count[i], fsize[i]);
489             }
490
491             /* close */
492             close(fd[i]);
493             fd[i] = -1;
494             ptr += fsize[i];
495             DEBUG_IFM("RM[%d] len = %d\n", i, count[i]);
496         }
497         break;
498     }
499
500     /* Collector --> Verifier */
501     case NEW_RIMM_SET:
502     {
503         /* check */
504         if (conf->newrm_num == 0) {
505             /* New RM is missing => send Error massage */
506             DEBUG_IFM("New RM is missing. send Error massage\n");
507             ctx->ifm_errno = PTS_FATAL;
508             ctx->ifm_strerror = smalloc_assert("New Manifest not found, check the collector");
509             goto error;
510         }
511
512         /* setup TLV header  (2/2) */
513         length = 16 + 4;  // UUID + num
514         for (i = 0; i < conf->newrm_num; i++) {
515             fd[i] = open(ctx->conf->newrm_filename[i], O_RDONLY);
516             if (fd[i] < 0) {
517                 // 20101124 SM must be a fullpath for Daemon
518                 LOG(LOG_ERR, "Error RM file, %s not found\n", ctx->conf->newrm_filename[i]);
519                 /* send Error massage */
520                 ctx->ifm_errno = PTS_FATAL;
521                 ctx->ifm_strerror =
522                     smalloc_assert("New Manifest file not found, check the collector");
523                 goto error;
524             }
525             /* check the size */
526             if (-1 == fstat(fd[i], &st[i])) {
527                 LOG(LOG_ERR, "fstat failed with errno %d\n", errno);
528                 goto error;
529             }
530             fsize[i] = st[i].st_size;
531             length += 4 + fsize[i];
532         }
533
534
535         DEBUG_IFM("writePtsTlv - NEW_RIMM_SET, length = %d", length);
536
537         buf = getTlvBuffer(type, length);
538         if (buf == NULL) {
539             LOG(LOG_ERR, "getTlvBuffer() is null");
540             goto error;
541         }
542         ptr = 12;
543
544
545         // UUID
546         memcpy(&buf[ptr], ctx->conf->newrm_uuid->uuid, 16);
547         ptr += 16;
548
549         // NUM of RM
550         num = htonl(conf->newrm_num);
551         memcpy(&buf[ptr], (BYTE *)&num, 4);
552         ptr += 4;
553
554         for (i = 0; i< conf->newrm_num; i++) {
555             // length of RM[i]
556             num = htonl(fsize[i]);
557             memcpy(&buf[ptr], (BYTE *)&num, 4);
558             ptr += 4;
559             // RM[i] body
560             count[i] = copyfile(&buf[ptr], fd[i], fsize[i]);
561             /* close */
562             close(fd[i]);
563             fd[i] = -1;
564             ptr += fsize[i];
565             DEBUG_IFM("RM[%d] len = %d\n", i, count[i]);
566         }
567         break;
568     }
569
570     case NONCE:
571     {
572         length = ctx->nonce->nonce_length;
573         buf = getTlvBuffer(type, length);
574         if (buf == NULL) {
575             LOG(LOG_ERR, "getTlvBuffer() is null");
576             goto error;
577         }
578         memcpy(&buf[12], ctx->nonce->nonce, length);
579         break;
580     }
581
582     case INTEGRITY_REPORT:
583     {
584         /* generate new IR, giving us a file descriptor corresponding
585            to an already deleted file for added security - once the file
586            gets closed you lose the IR! */
587         rc = genIr(ctx, &fd[0]);
588         if (rc != PTS_SUCCESS) {
589             LOG(LOG_ERR, "writePtsTlvToSock - gen IR failed\n");
590             /* send Error massage */
591             ctx->ifm_errno = PTS_FATAL;
592             ctx->ifm_strerror = smalloc_assert("Generation of IR failed");
593             goto error;
594         }
595
596         /* check the IR size */
597         if (-1 == fstat(fd[0], &st[0])) {
598             LOG(LOG_ERR, "fstat failed with errno %d\n", errno);
599             goto error;
600         }
601         fsize[0] = st[0].st_size;
602         length = fsize[0];
603
604         buf = getTlvBuffer(type, length);
605         if (buf == NULL) {
606             LOG(LOG_ERR, "getTlvBuffer() is null");
607             goto error;
608         }
609         ptr = 12;
610
611         if (-1 == lseek(fd[0], 0, SEEK_SET)) {
612             LOG(LOG_ERR, "Could not seek to start of %s (fd '%d')\n", ctx->conf->ir_filename, fd[0]);
613             goto error;
614         }
615
616         count[0] = copyfile(&buf[ptr], fd[0], fsize[0]);
617         if (count[0] != fsize[0]) {
618             LOG(LOG_ERR, "copyfile() faild %d != %d\n", count[0], fsize[0]);
619         }
620
621         /* close */
622         close(fd[0]);
623         fd[0] = -1;
624
625         break;
626     }
627
628 #ifdef CONFIG_AIDE
629     case AIDE_DATABASE:  /* AIDE DATABASE: C -> V */
630     {
631         /* setup TLV header  (2/2) */
632         /* body */
633         if (ctx->conf->aide_database_filename == NULL) {
634             // Test
635             DEBUG("writePtsTlvToSock - Error AIDE DB file is not configured\n");
636             ctx->ifm_errno = PTS_FATAL;
637             ctx->ifm_strerror = smalloc_assert("AIDE DB file is not configured");
638             goto error;
639         } else {
640             fd[0] = open(ctx->conf->aide_database_filename, O_RDONLY);
641             if (fd[0] < 0) {
642                 /* AIDE file is missing, erorr */
643                 LOG(LOG_ERR, "writePtsTlvToSock - Error AIDE DB file, %s not found\n",
644                     ctx->conf->aide_database_filename);
645                 /* send Error massage */
646                 ctx->ifm_errno = PTS_FATAL;
647                 ctx->ifm_strerror = smalloc_assert("AIDE file not found");
648                 goto error;
649             } else {
650                 /* OK */
651                 if (-1 == fstat(fd[0], &st[0])) {
652                     LOG(LOG_ERR, "fstat failed with errno %d\n", errno);
653                     goto error;
654                 }
655                 fsize[0] = st[0].st_size;
656                 length = fsize[0];
657             }
658         }
659
660         buf = getTlvBuffer(type, length);
661         if (buf == NULL) {
662             LOG(LOG_ERR, "getTlvBuffer() is null");
663             goto error;
664         }
665         ptr = 12;
666
667
668         if (length > 0) {
669             // BODY1
670             count[0] = copyfile(&buf[ptr], fd[0], fsize[0]);
671             if (count[0] != fsize[0]) {
672                 LOG(LOG_ERR, "copyfile() faild %d != %d\n", count[0], fsize[0]);
673             }
674
675             /* close */
676             close(fd[0]);
677             fd[0] = -1;
678
679             DEBUG_IFM("writePtsTlv - AIDE_DATABASE, file =  %s\n",
680                 ctx->conf->aide_database_filename);
681             // DEBUG_IFM("AIDE DATABASE len = %d\n", count[0]);
682         }
683         DEBUG_IFM("writePtsTlv - AIDE_DATABASE, length = %d", length);
684         break;
685     }
686 #endif  // CONFIG_AIDE
687
688
689     case DH_NONCE_PARAMETERS_REQUEST:  /* DH: Initiator -> Respondor */
690     {
691         /* setup TLV header  (2/2) */
692         length = 4;
693         buf = getTlvBuffer(type, length);
694         if (buf == NULL) {
695             goto error;
696         }
697         ptr = 12;
698
699         /* Send DH Nonce */
700         buf[0] = ctx->nonce->req->reserved;
701         buf[1] = ctx->nonce->req->min_nonce_len;
702         memcpy(&buf[ptr], buf, 2);
703         ptr += 2;
704
705         nbou16 = htons(ctx->nonce->req->dh_group_set);
706         memcpy(&buf[ptr], (BYTE *)&nbou16, 2);
707         ptr += 2;
708
709         DEBUG_IFM("writePtsTlv - DH_NONCE_PARAMETERS_REQUEST, length = %d", length);
710         break;
711     }
712
713     case DH_NONCE_PARAMETORS_RESPONSE:  /* DH: IRespondor -> Initiator */
714     {
715         /* setup TLV header  (2/2) */
716         length =
717             4 + 4 +
718             ctx->nonce->respondor_nonce_length +
719             ctx->nonce->pubkey_length;
720
721         buf = getTlvBuffer(type, length);
722         if (buf == NULL) {
723             LOG(LOG_ERR, "getTlvBuffer() is null");
724             goto error;
725         }
726         ptr = 12;
727
728         /* Send DH param  */
729         buf[0] = ctx->nonce->res->reserved[0];
730         buf[1] = ctx->nonce->res->reserved[1];
731         buf[2] = ctx->nonce->res->reserved[2];
732         buf[3] = ctx->nonce->res->nonce_length;
733         memcpy(&buf[ptr], buf, 4);
734         ptr += 4;
735
736         nbou16 = htons(ctx->nonce->res->selected_dh_group);
737         memcpy(&buf[ptr], (BYTE *)&nbou16, 2);
738         ptr += 2;
739
740         nbou16 = htons(ctx->nonce->res->hash_alg_set);
741         memcpy(&buf[ptr], (BYTE *)&nbou16, 2);
742         ptr += 2;
743
744         /* nonce */
745         memcpy(
746             &buf[ptr],
747             ctx->nonce->respondor_nonce,
748             ctx->nonce->respondor_nonce_length);
749         ptr += ctx->nonce->respondor_nonce_length;
750
751         /* send dh_respondor_public */
752         memcpy(
753             &buf[ptr],
754             ctx->nonce->pubkey,
755             ctx->nonce->pubkey_length);
756         ptr += ctx->nonce->pubkey_length;
757
758         DEBUG_IFM("writePtsTlv - DH_NONCE_PARAMETORS_RESPONSE, length = %d", length);
759         break;
760     }
761
762     case DH_NONCE_FINISH: /* DH: Initiator -> Respondor */
763     {
764         /* setup TLV header  (2/2) */
765         length =
766             4 +
767             ctx->nonce->initiator_nonce_length +
768             ctx->nonce->pubkey_length;
769
770         buf = getTlvBuffer(type, length);
771         if (buf == NULL) {
772             LOG(LOG_ERR, "getTlvBuffer() is null");
773             goto error;
774         }
775         ptr = 12;
776
777         /* Send IF-M TLV header */
778
779         /* Send */
780         buf[0] = ctx->nonce->fin->reserved = 0;
781         buf[1] = ctx->nonce->fin->nonce_length = ctx->nonce->initiator_nonce_length;
782         memcpy(&buf[ptr], (BYTE *)&buf, 2);
783         ptr += 2;
784
785         nbou16 = htons(ctx->nonce->fin->selected_hash_alg);
786         memcpy(&buf[ptr], (BYTE *)&nbou16, 2);
787         ptr += 2;
788
789         /* send dh_initiator_pubkey */
790         memcpy(&buf[ptr], ctx->nonce->pubkey, ctx->nonce->pubkey_length);
791         ptr += ctx->nonce->pubkey_length;
792
793         /* send dh_initiator_nonce */
794         memcpy(
795             &buf[ptr],
796             ctx->nonce->initiator_nonce,
797             ctx->nonce->initiator_nonce_length);
798         ptr += ctx->nonce->initiator_nonce_length;
799
800         DEBUG_IFM("writePtsTlv - DH_NONCE_FINISH, length = %d", length);
801         break;
802     }
803
804     case OPENPTS_ERROR:
805     {
806         /* setup TLV header  (2/2) */
807         // TODO
808         if (ctx->ifm_strerror != NULL) {
809             length = 4 + 4 + strlen(ctx->ifm_strerror);
810         } else {
811             length = 4 + 4 + 0;
812         }
813
814         buf = getTlvBuffer(type, length);
815         if (buf == NULL) {
816             LOG(LOG_ERR, "getTlvBuffer() is null");
817             goto error;
818         }
819         ptr = 12;
820
821         {
822             UINT32 ifm_errno;
823             UINT32 size = 0;
824             UINT32 len = 0;
825             /* send error code */
826             ifm_errno = htonl(ctx->ifm_errno);
827             memcpy(&buf[ptr], (BYTE *)&ifm_errno, 4);
828             ptr += 4;
829
830             /* send msg num */
831
832             if (ctx->ifm_strerror != NULL) {
833                 len = strlen(ctx->ifm_strerror);
834                 size = htonl(len);
835                 memcpy(&buf[ptr], (BYTE *)&size, 4);
836                 ptr += 4;
837
838                 memcpy(&buf[ptr], (BYTE *)&ctx->ifm_strerror, len);
839                 ptr += len;
840                 /* free */
841                 xfree(ctx->ifm_strerror);
842             } else {
843                 size = 0;
844                 memcpy(&buf[ptr], (BYTE *)&size, 4);
845                 ptr += 4;
846             }
847         }
848
849         DEBUG_IFM("writePtsTlv - OPENPTS_ERROR, length = %d", length);
850         break;
851     }
852
853     default:
854         // BAD type
855         LOG(LOG_ERR, "BAD IF-M OPENPTS MESSAGE TYPE, type=0x%x\n", type);
856         return NULL;
857     }
858
859     DEBUG_IFM("IF-M message, type=0x%x, length=%d\n",
860         type, length);
861     DEBUG("writePtsTlvToSock - done\n");
862
863     *len = 12 + length;
864     return buf;
865
866   error:
867     /* close files*/
868     for (i = 0; i < MAX_RM_NUM; i++) {
869         if (fd[i] >= 0) close(fd[i]);
870     }
871
872     *len = 0;
873     return NULL;
874 }
875
876 /**
877  * write IF-M PTS message ()
878  *
879  * we are using sendfile() here and send the data steb by step. 
880  * but IF-M of IMC/IMV version need to create whole blob to send.
881  *
882  * v0.2.4 - sendfile() not work with ptsc. use my_sendfile()
883  *
884  * Retrun
885  *  length of write data
886  *  -1 ERROR
887  */
888 int writePtsTlv(OPENPTS_CONTEXT *ctx, int fdout, int type) {
889     int rc = -1;
890     BYTE *message;
891     int length = 0;
892     int len;
893
894     DEBUG_CAL("writePtsTlvToSock - start\n");
895
896     /* check */
897     if (ctx == NULL) {
898         LOG(LOG_ERR, "null input");
899         return -1;
900     }
901
902     message = getPtsTlvMessage(ctx, type, &length);
903     if (message != NULL) {
904         rc = wrapWrite(fdout, message, length);
905         DEBUG_IFM("writePtsTlv - type=%d, length = %d", type, length);
906     } else {
907         DEBUG_IFM("getPtsTlvMessage() is null");
908         goto error;
909     }
910
911     DEBUG_CAL("writePtsTlvToSock - done\n");
912
913     /* done */
914     rc = length;
915     return rc;
916
917   error:
918     DEBUG_IFM("writePtsTlvToSock() fail, send error mgs\n");
919
920     /* send ERROR */
921     len = writePtsTlv(ctx, fdout, OPENPTS_ERROR);
922     if (len < 0) {
923         LOG(LOG_ERR, "send OPENPTS_ERROR was faild");
924     }
925
926     return -1;
927 }