wtls_pdu.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:40k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /* 
  2.  * wtls_pdu.c: pack and unpack WTLS packets
  3.  *
  4.  * Generates packing and unpacking code from wtls_pdu.def.
  5.  *
  6.  */
  7. #include "gwlib/gwlib.h"
  8. #if (HAVE_WTLS_OPENSSL)
  9. #include "gwlib/octstr.h"
  10. #include "wtls_pdu.h"
  11. #include "wtls_pdusupport.h"
  12. #include "wtls_statesupport.h"
  13. KeyExchangeSuite client_key_exchange_algo = rsa_anon;
  14. PublicKeyAlgorithm public_key_algo;
  15. SignatureAlgorithm signature_algo;
  16. int seqnum;
  17. wtls_Payload* wtls_payload_unpack_from_offset (Octstr *data, int *offset);
  18. wtls_PDU *wtls_pdu_create(int type) {
  19.         wtls_PDU *pdu;
  20.         
  21.         pdu = gw_malloc(sizeof(*pdu));
  22.         pdu->type = type;
  23.         pdu->reserved = 0;
  24.         pdu->cipher = 0;
  25.         pdu->seqnum = 0;
  26.         pdu->rlen = 0;
  27.         
  28.         switch (pdu->type) {
  29.         case ChangeCipher_PDU:
  30.                 pdu->u.cc.change = 1;
  31. break;
  32.         case Alert_PDU:
  33.                 pdu->u.alert.level = 0;
  34.                 pdu->u.alert.desc = 0;
  35.                 pdu->u.alert.chksum = 0;
  36. break;
  37.         case Handshake_PDU:
  38.                 pdu->u.handshake.msg_type = 0;
  39.                 pdu->u.handshake.length = 0;
  40. break;
  41.         case Application_PDU:
  42.                 pdu->u.application.data = NULL;
  43. break;
  44.         default:
  45.                 warning(0, "Cannot create unknown WTLS PDU type %d", pdu->type);
  46.                 break;
  47.         }
  48.         return pdu;
  49. }
  50. void wtls_payload_destroy(wtls_Payload *payload) {
  51. octstr_destroy(payload->data);
  52. gw_free(payload);
  53. }
  54. void wtls_pdu_destroy(wtls_PDU *pdu) {
  55.         if (pdu == NULL)
  56.                 return;
  57.         switch (pdu->type) {
  58.         case ChangeCipher_PDU:
  59. /* no memory was allocated for ChangeCipher_PDU */
  60.   break;
  61.         case Alert_PDU:
  62. octstr_destroy(pdu->u.alert.chksum );
  63. break;
  64.         case Handshake_PDU:
  65.                 switch (pdu->u.handshake.msg_type) {
  66.                 case hello_request:
  67. break;
  68.                 case client_hello:
  69. destroy_random(pdu->u.handshake.client_hello->random);
  70. octstr_destroy(pdu->u.handshake.client_hello->session_id);
  71. destroy_key_list(pdu->u.handshake.client_hello->client_key_ids);
  72. destroy_key_list(pdu->u.handshake.client_hello->trusted_key_ids);
  73. destroy_ciphersuite_list(pdu->u.handshake.client_hello->ciphersuites);
  74. destroy_compression_method_list(pdu->u.handshake.client_hello->comp_methods);
  75. /* destroy the client_hello struct */
  76. gw_free(pdu->u.handshake.client_hello);
  77. break;
  78.                 case server_hello:
  79. destroy_random(pdu->u.handshake.server_hello->random);
  80. octstr_destroy(pdu->u.handshake.server_hello->session_id);
  81. /* destroy the server_hello struct */
  82. gw_free(pdu->u.handshake.server_hello);
  83. break;
  84.                 case certificate:
  85.                         switch (pdu->u.handshake.certificate->certificateformat) {
  86.                         case WTLSCert:
  87. destroy_wtls_certificate(pdu->u.handshake.certificate->wtls_certificate);
  88.                                 break;
  89.                         case X509Cert:
  90. octstr_destroy(pdu->u.handshake.certificate->x509_certificate);
  91.                                 break;
  92.                         case X968Cert:
  93. octstr_destroy(pdu->u.handshake.certificate->x968_certificate);
  94.                                 break;
  95.                         }
  96. gw_free(pdu->u.handshake.certificate);
  97. break;
  98.                 case server_key_exchange:
  99. destroy_param_spec(pdu->u.handshake.server_key_exchange->param_spec);
  100.                         switch (client_key_exchange_algo) {
  101.                         case rsa_anon:
  102. destroy_rsa_pubkey(pdu->u.handshake.server_key_exchange->rsa_params);
  103. break;
  104.                         case dh_anon:
  105.                                 destroy_dh_pubkey(pdu->u.handshake.server_key_exchange->dh_params);
  106. break;
  107.                         case ecdh_anon:
  108.                                 destroy_ec_pubkey(pdu->u.handshake.server_key_exchange->ecdh_params);
  109. break;
  110. }
  111. gw_free(pdu->u.handshake.server_key_exchange);
  112. break;
  113.                 case client_key_exchange:
  114.                         switch (client_key_exchange_algo) {
  115.                         case rsa:
  116.                         case rsa_anon:
  117.                                 destroy_rsa_encrypted_secret(pdu->u.handshake.client_key_exchange->rsa_params);
  118.                                 break;
  119.                         case dh_anon:
  120.                                 destroy_dh_pubkey(pdu->u.handshake.client_key_exchange->dh_anon_params);
  121.                                 break;
  122.                         case ecdh_anon:
  123.                         case ecdh_ecdsa:
  124.                                 destroy_ec_pubkey(pdu->u.handshake.client_key_exchange->ecdh_params);
  125. break;
  126. }
  127. gw_free(pdu->u.handshake.client_key_exchange);
  128. break;
  129.                 case server_hello_done:
  130. /* nothing to do here */
  131.                      break;
  132.                 }
  133. break;
  134.         case Application_PDU:
  135. octstr_destroy(pdu->u.application.data);
  136. break;
  137.         }
  138.         gw_free(pdu);
  139. }
  140. /* This function will pack a list of WTLS PDUs into a single Octstr, and return
  141.    that Octstr. */
  142. Octstr* wtls_pack_payloadlist (List* payloadlist) {
  143.         Octstr *returnData=0, *tempData1=0, *tempData2 = 0;
  144.         wtls_Payload* retrievedPDU;
  145.         
  146.         /* Assert that our payloadlist is not NULL */
  147.         gw_assert (payloadlist != NULL);
  148.         /* Initialise our return Octstr */
  149.         returnData = octstr_create("");
  150.         
  151.         /* While there are PDUs remaining in our list */
  152.         while (list_len(payloadlist) > 0) {                
  153.                 /* Retrieve the next payload from the payloadlist */
  154.                 retrievedPDU = (wtls_Payload*) list_extract_first (payloadlist);
  155.                 /* Pack the PDU */
  156.                 tempData2 = wtls_payload_pack(retrievedPDU);
  157.                 /* Shift the current stuff in returnData to a temporary pointer */
  158.                 tempData1 = returnData;
  159.                 
  160.                 /* Tack it onto our Octstr */
  161.                 returnData = octstr_cat(tempData1, tempData2);
  162.                 /* And now, we can get rid of both tempData1 and tempData2 */
  163.                 octstr_destroy (tempData1);
  164.                 octstr_destroy (tempData2);                
  165.         }
  166.         
  167.         /* Is the Octstr we finish with of length > 0? */
  168.         if (octstr_len(returnData) > 0) {        
  169.                 /* Return the Octstr */
  170.                 return returnData;
  171.         }
  172.         
  173.         /* Otherwise, return NULL */
  174.         return NULL;
  175. }
  176. /* This function will unpack an Octstr and return a list of all PDUs contained
  177.    within that Octstr. If the contents of the packet are garbled in some fashion,
  178.    and one packet fails to be decoded correctly, we will continue regardless, and
  179.    a partial list will be returned. NULL is returned if no PDUs can be successfully
  180.    decoded from the supplied data */
  181. List* wtls_unpack_payloadlist (Octstr *data) {
  182.         List* payloadlist = NULL;
  183.         int offset = 0;
  184.         int dataLength = 0;
  185.         wtls_Payload* tempPayload;
  186.         
  187.         /* Has somebody passed in an unpack of a null pointer ? */
  188.         gw_assert(data != NULL);
  189.         
  190.         /* Initialise our list */
  191.         payloadlist = list_create();
  192.         dataLength = octstr_len(data);
  193.         
  194.         /* While offset is less than the size of the data */
  195.         while( offset < dataLength) {
  196.                 debug("wtls:wtls_unpack_payloadlist",0,"Offset is now : %d", offset);
  197.                 /* Unpack from the supplied offset. This will bump up the value of offset */
  198.                 tempPayload = wtls_payload_unpack_from_offset (data, &offset);
  199.                 
  200.                 /* If the packet returned is not NULL */
  201.                 if (tempPayload != NULL) {
  202.                         /* Add the returned packet to the current list of packets */
  203.                         list_append(payloadlist, (void*) tempPayload);
  204.                 }
  205.         }
  206.         debug("wtls:wtls_unpack_payloadlist",0,"Finished, found %d PDUs", list_len(payloadlist));
  207.         
  208.         /* If the length of the list is greater than 0 */
  209.         if (list_len(payloadlist) > 0) {
  210.                 /* Return the List */
  211.                 return payloadlist;
  212.         }
  213.         
  214.         /* Otherwise return NULL */
  215.         return NULL;
  216. }
  217. /* This function tries to determine the length of the PDU at the start of the
  218.    supplied Octstr using (somewhat) intelligent means. If the packet is screwed
  219.    up in some fashion, returns length -1. Returns an int. */
  220. int wtls_payload_guess_length(Octstr* data) {
  221.         int type = 0, lengthFlag = 0, lengthSize = 0, pdu_length = 0;
  222.         long lengthOffset = 1;
  223.         
  224.         /* Is the fragment length indicator on? */
  225.         lengthFlag = octstr_get_bits(data, 0, 1);
  226.         if (lengthFlag) {
  227.                 lengthSize = 2;
  228.         }
  229.         
  230.         /* Is the sequence number indicator on? */
  231.         if (octstr_get_bits(data, 1, 1)) {
  232.                 /* Yes, so hop over two extra bytes when reading the length */
  233.                 lengthOffset += 2;
  234.         }
  235.         /* the message type */
  236.         type = octstr_get_bits(data, 4, 4);
  237.         
  238.         /* If fragment length is turned on, jump to the necessary spot */
  239.         if (lengthFlag == 1) {
  240.                 /* After this, lengthOffset + pdu_length == the total length of the PDU */
  241.                 pdu_length = unpack_int16(data, &lengthOffset);             
  242.         }
  243.         /* Oh great, so it's not switched on. How considerate. We'll have to make
  244.            a reasonable guess as to what it might be. */
  245.         else {
  246.                 switch (type) {
  247.                 case ChangeCipher_PDU:
  248.                         /* They're really short */
  249.                         pdu_length = 1;
  250.                         break;
  251.                         
  252.                 case Alert_PDU:
  253.                         /* They're a bit longer */
  254.                         pdu_length = 6;
  255.                         break;
  256.                 default:
  257.                         /* Otherwise just give up and play dead */
  258.                         pdu_length = -1;
  259.                         break;
  260.                 }
  261.         }
  262.         /* And that's the length of the contents, now just add the other doodads on */
  263.         if (pdu_length == -1) {
  264.                 return -1;
  265.         }
  266.         else {
  267.                 /* The pdu length, plus the sequence number, plus the length of the length value,
  268.                    plus the actual header byte */
  269.                 return (pdu_length + lengthOffset);
  270.         }
  271. }
  272. /* This function will unpack an Octstr, starting at the specified offset, and
  273.    return the corresponding wtls_PDU* which was generated from that offset. Offset
  274.    is changed during the running of this function, and ends up as the octet at the start of the
  275.    next pdu */
  276. wtls_Payload* wtls_payload_unpack_from_offset (Octstr *data, int *offset) {
  277.         int guessedPayloadLength = 0;
  278.         int dataLength = 0;
  279.         Octstr* dataFromOffset = 0;
  280.         Octstr* dataFromOffsetToLength = 0;
  281.         wtls_Payload* returnPayload = 0;
  282.         
  283.         /* This would be a sure sign of trouble */
  284.         gw_assert (offset != NULL);
  285.         gw_assert (data != NULL);
  286.         gw_assert (octstr_len(data) >= *offset);
  287.         dataLength = octstr_len(data);
  288.         
  289.         /* First, we need to figure out how long a PDU starting from
  290.            the specified offset is going to be. We need to peek quickly into the
  291.            PDU to check this */
  292.         dataFromOffset = octstr_copy(data, *offset, dataLength);
  293.         guessedPayloadLength = wtls_payload_guess_length(dataFromOffset);
  294.         /* Ooops. Something's wrong. This requested PDU is screwed up. */
  295.         if (guessedPayloadLength == -1) {
  296.                 *offset = dataLength;
  297.                 return NULL;
  298.         }
  299.         
  300.         /* Quit if we discover that the PDU length plus the requested offset is
  301.            larger than the length of the data supplied - this would mean that we
  302.            would overrun our data, and therefore something is corrupt in this PDU.
  303.            Set the offset as the data length, which will indicate we've gone as far
  304.            as we can */
  305.         if ((*offset + guessedPayloadLength) > dataLength) {
  306.                 *offset = dataLength;
  307.                 return NULL;
  308.         }
  309.         
  310.         /* If we pass that test, set offset to the correct return value */
  311.         *offset += guessedPayloadLength;
  312.         
  313.         /* Copy the octstr again, so that we end up with an octstr containing
  314.            just the PDU we want */
  315.         dataFromOffsetToLength = octstr_copy(dataFromOffset, 0, guessedPayloadLength);
  316.         
  317.         /* Submit that octstr to the wtls_message_unpack function */
  318.         returnPayload = wtls_payload_unpack(dataFromOffsetToLength);
  319.         
  320.         /* Test to make sure the returned PDU is good */
  321.         if (returnPayload != NULL) {        
  322.                 /* And return the PDU to our caller */
  323.                 return returnPayload;
  324.         }
  325.         
  326.         /* Otherwise return NULL */
  327.         return NULL;
  328. }        
  329. wtls_Payload *wtls_payload_unpack(Octstr *data) {
  330.         wtls_Payload *payload = NULL;
  331. Octstr *buffer;
  332.         long bitpos = 0, charpos = 0;
  333.         int msg_length;
  334.         
  335.         gw_assert(data != NULL);
  336.         payload = gw_malloc(sizeof(wtls_Payload));
  337.         /* the record field length flag */
  338.         payload->rlen = octstr_get_bits(data, bitpos, 1);
  339.         bitpos += 1;
  340.         /* the sequence number flag */
  341.         payload->seqnum = octstr_get_bits(data, bitpos, 1);
  342.         bitpos += 1;
  343.         /* the cipher usage flag */
  344.         payload->cipher = octstr_get_bits(data, bitpos, 1);
  345.         bitpos += 1;
  346.         /* the reserved bit */
  347.         payload->reserved = octstr_get_bits(data, bitpos, 1);
  348.         bitpos += 1;
  349.         /* the message type */
  350.         payload->type = octstr_get_bits(data, bitpos, 4);
  351.         bitpos += 4;
  352.         charpos += 1;
  353.         
  354.         /* get the sequence number if present */
  355.         if(payload->seqnum) {
  356.                 seqnum = unpack_int16(data, &charpos);
  357.         }
  358.         
  359.         /* get the WTLS plaintext length if present */
  360.         if(payload->rlen) {
  361.                 msg_length = unpack_int16(data, &charpos);
  362.         }
  363. /* the part of data that has just been processed is not
  364.    needed anymore. We delete it. What is left of data is
  365.    the payload. */
  366. octstr_delete(data, 0, charpos);
  367. payload->data = data;
  368. return payload;
  369. }
  370. void *wtls_payloadlist_destroy(List* payloadList) {
  371. wtls_Payload* currentPayload;
  372. int listLen, i;
  373. listLen = list_len(payloadList);
  374. for( i=0; i<listLen; i++) {
  375. currentPayload = (wtls_Payload *)list_get(payloadList, i);
  376. wtls_payload_destroy(currentPayload);
  377. }
  378. /* delete the list itself */
  379. gw_free(payloadList);
  380. }
  381. wtls_PDU *wtls_pdu_unpack(wtls_Payload *payload, WTLSMachine* wtls_machine) {
  382.         wtls_PDU *pdu = NULL;
  383.         Octstr *buffer;
  384.         long bitpos = 0, charpos = 0;
  385.         int msg_length;
  386.         
  387.         gw_assert(payload->data != NULL);
  388.         pdu = gw_malloc(sizeof(*pdu));
  389. pdu->type = payload->type;
  390. pdu->reserved = payload->reserved;
  391. pdu->cipher = payload->cipher;
  392. pdu->seqnum = payload->seqnum;
  393. pdu->rlen = payload->rlen;
  394. /* is the PDU encrypted ? */
  395. /*
  396. if(pdu->cipher) {
  397. buffer = wtls_decrypt(payload->data, wtls_machine);
  398. }
  399. else {
  400. */
  401. buffer = payload->data;
  402. /*
  403. }
  404. */
  405.         switch (pdu->type) {
  406.         case ChangeCipher_PDU:
  407.                 pdu->u.cc.change = octstr_get_char(buffer, charpos);
  408.                 charpos += 1;
  409.                 break;
  410.         case Alert_PDU:
  411.                 pdu->u.alert.level = octstr_get_char(buffer, charpos);
  412.                 charpos += 1;
  413.                 pdu->u.alert.desc = octstr_get_char(buffer, charpos);
  414.                 charpos += 1;
  415.                 pdu->u.alert.chksum = unpack_octstr_fixed(buffer, &charpos, 4);
  416.                 break;  
  417.         case Handshake_PDU:
  418.                 pdu->u.handshake.msg_type = octstr_get_char(buffer, charpos);
  419.                 charpos += 1;
  420.                 pdu->u.handshake.length = unpack_int16(buffer, &charpos);
  421.                 switch (pdu->u.handshake.msg_type) {
  422.                 case hello_request:
  423.                         break;
  424.                 case client_hello:
  425.                         pdu->u.handshake.client_hello = (ClientHello *)gw_malloc(sizeof(ClientHello));
  426.                         pdu->u.handshake.client_hello->clientversion = octstr_get_char(buffer, charpos);
  427.                         charpos += 1;
  428.                         pdu->u.handshake.client_hello->random = unpack_random(buffer, &charpos);
  429.                         pdu->u.handshake.client_hello->session_id = unpack_octstr(buffer, &charpos);
  430.                         /* pack the list of keys */
  431.                         pdu->u.handshake.client_hello->client_key_ids = unpack_key_list(buffer, &charpos);
  432.                         pdu->u.handshake.client_hello->trusted_key_ids = unpack_key_list(buffer, &charpos);
  433.                         /* pack the list of CipherSuites */
  434.                         pdu->u.handshake.client_hello->ciphersuites = unpack_ciphersuite_list(buffer, &charpos);
  435.                         /* CompressionMethods */
  436.                         pdu->u.handshake.client_hello->comp_methods = unpack_compression_method_list(buffer, &charpos);
  437.                         pdu->u.handshake.client_hello->snmode = octstr_get_char(buffer, charpos);
  438.                         charpos += 1;
  439.                         pdu->u.handshake.client_hello->krefresh = octstr_get_char(buffer, charpos);
  440.                         charpos += 1;
  441.                         break;
  442.                 case server_hello:
  443.                         pdu->u.handshake.server_hello = (ServerHello *)gw_malloc(sizeof(ServerHello));
  444.                         pdu->u.handshake.server_hello->serverversion = octstr_get_char(buffer, charpos);
  445.                         charpos += 1;
  446.                         pdu->u.handshake.server_hello->random = unpack_random(buffer, &charpos);
  447.                         pdu->u.handshake.server_hello->session_id = unpack_octstr(buffer, &charpos);
  448.                         charpos += 1;
  449.                         pdu->u.handshake.server_hello->client_key_id
  450.                                 = octstr_get_char(buffer, charpos);
  451.                         charpos += 1;
  452.                         /* CypherSuite */
  453.                         pdu->u.handshake.server_hello->ciphersuite->bulk_cipher_algo
  454.                                 = octstr_get_char(buffer, charpos);
  455.                         charpos += 1;
  456.                         pdu->u.handshake.server_hello->ciphersuite->mac_algo
  457.                                 = octstr_get_char(buffer, charpos);
  458.                         charpos += 1;
  459.                         /* CompressionMethod */
  460.                         pdu->u.handshake.server_hello->comp_method = octstr_get_char(buffer, charpos);
  461.                         charpos += 1;
  462.                         pdu->u.handshake.server_hello->snmode = octstr_get_char(buffer, charpos);
  463.                         charpos += 1;
  464.                         pdu->u.handshake.server_hello->krefresh = octstr_get_char(buffer, charpos);
  465.                         charpos += 1;
  466.                         break;
  467.                 case certificate:
  468.                         pdu->u.handshake.certificate = (Certificate *)gw_malloc(sizeof(Certificate));
  469.                         pdu->u.handshake.certificate->certificateformat = octstr_get_char(buffer, charpos);
  470.                         charpos += 1;
  471.                         switch (pdu->u.handshake.certificate->certificateformat) {
  472.                         case WTLSCert:
  473.                                 pdu->u.handshake.certificate->wtls_certificate = unpack_wtls_certificate(buffer, &charpos);
  474.                                 break;
  475.                         case X509Cert:
  476.                                 pdu->u.handshake.certificate->x509_certificate = unpack_octstr16(buffer, &charpos);
  477.                                 break;
  478.                         case X968Cert:
  479.                                 pdu->u.handshake.certificate->x968_certificate = unpack_octstr16(buffer, &charpos);
  480.                                 break;
  481.                         }
  482.                         break;
  483.                 case server_key_exchange:
  484.                         pdu->u.handshake.server_key_exchange = (ServerKeyExchange *)gw_malloc(sizeof(ServerKeyExchange));
  485.                         /* unpack the ParameterSpecifier  and ParameterSet*/
  486.                         pdu->u.handshake.server_key_exchange->param_spec
  487.                                 = unpack_param_spec(buffer, &charpos);
  488.                         switch (client_key_exchange_algo) {
  489.                         case rsa_anon:
  490.                                 pdu->u.handshake.server_key_exchange->rsa_params
  491.                                         = unpack_rsa_pubkey(buffer, &charpos);
  492.                                 break;
  493.                         case dh_anon:
  494.                                 pdu->u.handshake.server_key_exchange->dh_params
  495.                                         = unpack_dh_pubkey(buffer, &charpos);
  496.                                 break;
  497.                         case ecdh_anon:
  498.                                 pdu->u.handshake.server_key_exchange->ecdh_params
  499.                                         = unpack_ec_pubkey(buffer, &charpos);
  500.                                 break;
  501.                         }
  502.                         break;
  503.                 case client_key_exchange:
  504.                         pdu->u.handshake.client_key_exchange = (ClientKeyExchange *)gw_malloc(sizeof(ClientKeyExchange));
  505.                         switch (client_key_exchange_algo) {
  506.                         case rsa:
  507.                         case rsa_anon:
  508.                                 pdu->u.handshake.client_key_exchange->rsa_params
  509.                                         = unpack_rsa_encrypted_secret(buffer, &charpos);
  510.                                 break;
  511.                         case dh_anon:
  512.                                 pdu->u.handshake.client_key_exchange->dh_anon_params
  513.                                         = unpack_dh_pubkey(buffer, &charpos);
  514.                                 break;
  515.                         case ecdh_anon:
  516.                         case ecdh_ecdsa:
  517.                                 pdu->u.handshake.client_key_exchange->ecdh_params
  518.                                         = unpack_ec_pubkey(buffer, &charpos);
  519.                                 break;
  520.                         }
  521.                         break;
  522.                 case server_hello_done:
  523.                         /* empty */
  524.                         break;
  525.                 case finished:
  526.                         pdu->u.handshake.finished = (Finished *)gw_malloc(sizeof(Finished));
  527.                         pdu->u.handshake.finished->verify_data
  528.                                         = unpack_octstr_fixed(buffer, &charpos, 12);
  529. octstr_dump(pdu->u.handshake.finished->verify_data, 0);
  530.                         break;
  531.                 }
  532.                 break;
  533.         case Application_PDU:
  534.                 /* application message */
  535.                 pdu->u.application.data = octstr_duplicate(buffer);
  536.                 break;
  537.         default:
  538.                 debug("wap.wtls", 0, "%*sPDU: ", 0, "");
  539.                 octstr_dump(buffer, 0);
  540.                 panic(0, "Unpacking unknown WTLS PDU type %ld", (long) pdu->type);
  541.         }
  542.         return pdu;
  543. }
  544. Octstr *wtls_payload_pack(wtls_Payload *payload) {
  545.         Octstr *data;
  546.         long bitpos, charpos;
  547.         long messageSizePos, sizepos;
  548.         /* Used for length calculations */
  549.         int size;
  550.         
  551.         /* We rely on octstr_set_bits to lengthen our octstr as needed. */
  552.         data = octstr_create("");
  553.         bitpos = 0;
  554.         charpos = 0;
  555.         sizepos = 0;
  556.         
  557.         /* the record field length flag - always present*/
  558.         octstr_set_bits(data, bitpos, 1, 1);
  559.         bitpos += 1;
  560.         /* the sequence number flag */
  561.         octstr_set_bits(data, bitpos, 1, payload->seqnum);
  562.         bitpos += 1;
  563.         /* the cipher usage flag */
  564.         octstr_set_bits(data, bitpos, 1, payload->cipher);
  565.         bitpos += 1;
  566.         /* the reserved bit */
  567.         octstr_set_bits(data, bitpos, 1, payload->reserved);
  568.         bitpos += 1;
  569.         /* set the message type */
  570.         octstr_set_bits(data, bitpos, 4, payload->type);
  571.         bitpos += 4;
  572.         charpos += 1;
  573.         /* set the sequence number if present */
  574.         if(payload->seqnum) {
  575.                 charpos = pack_int16(data, charpos, payload->seqnum);
  576.         }
  577.         /* set the WTLS length  */
  578.         charpos = pack_int16(data, charpos, payload->rlen);
  579.         
  580.         /* append the data from the wtls_PDU */
  581.         octstr_insert(data, payload->data, octstr_len(data)); 
  582.         
  583.         return data;
  584. }
  585. wtls_Payload *wtls_pdu_pack(wtls_PDU *pdu, WTLSMachine* wtls_machine) {
  586.         Octstr *data, *buffer, *encryptedbuffer;
  587.         wtls_Payload *payload;
  588.         long bitpos, charpos;
  589.         long messageSizePos, sizepos;
  590.         /* Used for length calculations */
  591.         int size, recordType;
  592.         
  593. /* create the wtls_PDU */
  594. payload = (wtls_Payload *)gw_malloc(sizeof(wtls_Payload));
  595. payload->type = pdu->type;
  596. payload->reserved = pdu->reserved;
  597. payload->cipher = pdu->cipher;
  598. payload->seqnum = pdu->seqnum;
  599.         /* We rely on octstr_set_bits to lengthen our octstr as needed. */
  600.         data = octstr_create("");
  601.         buffer = octstr_create("");
  602.         bitpos = 0;
  603.         charpos = 0;
  604.         sizepos = 0;
  605.         
  606.         switch (pdu->type) {
  607.         case ChangeCipher_PDU:
  608.                 octstr_append_char(buffer, pdu->u.cc.change);
  609.                 charpos += 1;
  610.                 break;
  611.         case Alert_PDU:
  612.                 octstr_append_char(buffer, pdu->u.alert.level);
  613.                 charpos += 1;
  614.                 octstr_append_char(buffer, pdu->u.alert.desc);
  615.                 charpos += 1;
  616.                 charpos = pack_octstr_fixed(buffer, charpos, pdu->u.alert.chksum);
  617.                 charpos += 1;
  618.                 break;  
  619.         case Handshake_PDU:
  620.                 octstr_append_char(buffer, pdu->u.handshake.msg_type);
  621.                 charpos += 1;
  622.                 /* Save the location of the message size */
  623.                 messageSizePos = charpos;
  624.                 charpos = pack_int16 (buffer, charpos, pdu->u.handshake.length);
  625.                 switch (pdu->u.handshake.msg_type) {
  626.                 case hello_request:
  627.                         break;
  628.                 case client_hello:
  629.                         octstr_append_char(buffer, pdu->u.handshake.client_hello->clientversion);
  630.                         charpos += 1;
  631.                         charpos = pack_random(buffer, charpos, pdu->u.handshake.client_hello->random);
  632.                         octstr_append_char(buffer, octstr_len(
  633.                                 pdu->u.handshake.client_hello->session_id));
  634.                         charpos += 1;
  635.                         charpos = pack_octstr(buffer, charpos, pdu->u.handshake.client_hello->session_id);
  636.                         /* pack the list of keys */
  637.                         charpos = pack_key_list(buffer, charpos,
  638.                                                 pdu->u.handshake.client_hello->client_key_ids);
  639.                         charpos = pack_key_list(buffer, charpos,
  640.                                                 pdu->u.handshake.client_hello->trusted_key_ids);
  641.                         /* pack the list of CipherSuites */
  642.                         charpos = pack_ciphersuite_list(buffer, charpos,
  643.                                                         pdu->u.handshake.client_hello->ciphersuites);
  644.                         /* CompressionMethods */
  645.                         charpos = pack_compression_method_list(buffer, charpos,
  646.                                                                pdu->u.handshake.client_hello->comp_methods);
  647.                         octstr_append_char(buffer, pdu->u.handshake.client_hello->snmode);
  648.                         charpos += 1;
  649.                         octstr_append_char(buffer, pdu->u.handshake.client_hello->krefresh);
  650.                         charpos += 1;
  651.                         break;
  652.                 case server_hello:
  653.                         octstr_append_char(buffer, pdu->u.handshake.server_hello->serverversion);
  654.                         charpos += 1;
  655.                         charpos = pack_random(buffer,  charpos, pdu->u.handshake.server_hello->random);
  656.                         charpos = pack_octstr(buffer, charpos, pdu->u.handshake.server_hello->session_id);
  657.                         charpos += 1;
  658.                         octstr_append_char(buffer, pdu->u.handshake.server_hello->
  659.                                            client_key_id);
  660.                         charpos += 1;
  661.                         /* CypherSuite */
  662.                         octstr_append_char(buffer, pdu->u.handshake.server_hello->
  663.                                            ciphersuite->bulk_cipher_algo);
  664.                         charpos += 1;
  665.                         octstr_append_char(buffer, pdu->u.handshake.server_hello->
  666.                                            ciphersuite->mac_algo);
  667.                         charpos += 1;
  668.                         /* CompressionMethod */
  669.                         octstr_append_char(buffer, pdu->u.handshake.server_hello->comp_method);
  670.                         charpos += 1;
  671.                         octstr_append_char(buffer, pdu->u.handshake.server_hello->snmode);
  672.                         charpos += 1;
  673.                         octstr_append_char(buffer, pdu->u.handshake.server_hello->krefresh);
  674.                         charpos += 1;
  675.                         break;
  676.                 case certificate:
  677.                         octstr_append_char(buffer, pdu->u.handshake.certificate->certificateformat);
  678.                         charpos += 1;
  679.                         switch (pdu->u.handshake.certificate->certificateformat) {
  680.                         case WTLSCert:
  681.                                 charpos = pack_wtls_certificate(buffer, charpos, pdu->u.handshake.certificate->wtls_certificate);
  682.                                 break;
  683.                         case X509Cert:
  684.                                 charpos = pack_octstr16(buffer, charpos, pdu->u.handshake.certificate->x509_certificate);
  685.                                 break;
  686.                         case X968Cert:
  687.                                 charpos = pack_octstr16(buffer, charpos, pdu->u.handshake.certificate->x968_certificate);
  688.                                 break;
  689.                         }
  690.                         break;
  691.                 case server_key_exchange:
  692.             debug("wtls: ", 0,"Packing ServerKeyExchange");
  693.                         /* pack the ParameterSpecifier */
  694.                         charpos = pack_param_spec(buffer, charpos, pdu->u.handshake.server_key_exchange->param_spec);
  695.                         switch (client_key_exchange_algo) {
  696.                         case rsa_anon:
  697.                                 charpos = pack_rsa_pubkey(buffer, charpos, pdu->u.handshake.server_key_exchange->rsa_params);
  698.                                 break;
  699.                         case dh_anon:
  700.                                 charpos = pack_dh_pubkey(buffer, charpos, pdu->u.handshake.server_key_exchange->dh_params);
  701.                                 break;
  702.                         case ecdh_anon:
  703.                                 charpos = pack_ec_pubkey(buffer, charpos, pdu->u.handshake.server_key_exchange->ecdh_params);
  704.                                 break;
  705.                         }
  706.                         break;
  707.                 case client_key_exchange:
  708.                         switch (client_key_exchange_algo) {
  709.                         case rsa:
  710.                         case rsa_anon:
  711.                                 charpos = pack_rsa_encrypted_secret(buffer, charpos, pdu->u.handshake.client_key_exchange->rsa_params);
  712.                                 break;
  713.                         case dh_anon:
  714.                                 charpos = pack_dh_pubkey(buffer, charpos, pdu->u.handshake.client_key_exchange->dh_anon_params);
  715.                                 break;
  716.                         case ecdh_anon:
  717.                         case ecdh_ecdsa:
  718.                                 charpos = pack_ec_pubkey(buffer, charpos, pdu->u.handshake.client_key_exchange->ecdh_params);
  719.                                 break;
  720.                         }
  721.                         break;
  722.                 case server_hello_done:
  723.                         /* empty */
  724.                         break;
  725. case finished:
  726. charpos = pack_octstr_fixed(buffer, charpos, pdu->u.handshake.finished->verify_data);
  727. debug("wtls", 0, "verify_data (in pack)");
  728. octstr_dump(pdu->u.handshake.finished->verify_data,0 );
  729. break;
  730.                 }
  731.                 /* Change the length */
  732.                 size = octstr_len(buffer) - messageSizePos - 2;
  733.                 debug("wtls_msg.c:length",0,"Setting msg size to : %d",size);
  734.                 octstr_set_char(buffer, messageSizePos, (size & 0xFF00) >> 8);
  735. messageSizePos += 1;
  736. octstr_set_char(buffer, messageSizePos, (size & 0x00FF));
  737. /* we keep the handshake data to create the Finished PDU */
  738. octstr_append(wtls_machine->handshake_data, buffer);
  739.                 break;                
  740.         case Application_PDU:
  741.                 /* application message */
  742.                 charpos += pack_octstr(data, charpos, pdu->u.application.data);
  743.                 break;
  744.      default:
  745.                 panic(0, "Packing unknown WTLS PDU type %ld", (long) pdu->type);
  746.         }
  747.         
  748.         /* encrypt the buffer if needed */
  749.         if(pdu->cipher) {
  750. /* the MAC is calculated with the record type so we need it now */
  751. recordType = 1 << 7; /* length, always present */
  752. recordType |= pdu->seqnum << 6;
  753. recordType |= pdu->cipher << 5;
  754. recordType |= pdu->reserved << 4;
  755. recordType |= pdu->type;
  756.                 encryptedbuffer = wtls_encrypt(buffer, wtls_machine, recordType);
  757.                 payload->data = encryptedbuffer;
  758.         }
  759.         else {
  760.                 payload->data = buffer;
  761.         }
  762.         payload->rlen = octstr_len(payload->data);
  763.         debug("wtls", 0, "Packed PDU Length: %d", payload->rlen);
  764.         
  765.         return payload;
  766. }
  767. void wtls_pdu_dump(wtls_PDU *pdu, int level) {
  768. unsigned char *dbg = "wap.wtls";
  769. /* the message type */
  770. debug(dbg, 0, "%*sPDU type: %p", level, "", pdu->type);
  771. /* the reserved bit */
  772. debug(dbg, 0, "%*sReserved bit: %p", level, "", pdu->reserved);
  773. /* cipher usage flag */
  774. debug(dbg, 0, "%*sCipher in use: %p", level, "", pdu->cipher);
  775. /* the sequence number flag */
  776. debug(dbg, 0, "%*sSequence number in use: %p", level, "", pdu->seqnum);
  777. /* the record field length flag */
  778. debug(dbg, 0, "%*sRecord field length present: %p", level, "", pdu->rlen);
  779. switch (pdu->type) {
  780. case ChangeCipher_PDU:
  781. debug(dbg, 0, "%*sChangeCipher:", level, "");
  782. debug(dbg, 0, "%*sChange: %d", level+1, "", pdu->u.cc.change);
  783. break;
  784. case Alert_PDU:
  785. debug(dbg, 0, "%*sAlert:", level, "");
  786. debug(dbg, 0, "%*sLevel: %p", level+1, "", pdu->u.alert.level);
  787. debug(dbg, 0, "%*sDescription: %d", level+1, "", pdu->u.alert.desc);
  788. debug(dbg, 0, "%*sChecksum: %p", level+1, "", pdu->u.alert.chksum);
  789. break;
  790. case Handshake_PDU:
  791. debug(dbg, 0, "%*sHandshake:", level, "");
  792. debug(dbg, 0, "%*sMessage Type: %d", level+1, "", pdu->u.handshake.msg_type);
  793. debug(dbg, 0, "%*sLength: %d", level+1, "", pdu->u.handshake.length);
  794. switch (pdu->u.handshake.msg_type) {
  795. case hello_request:
  796. debug(dbg, 0, "%*sHelloRequest.", level, "");
  797. break;
  798. case client_hello:
  799. debug(dbg, 0, "%*sClientHello :", level, "");
  800. debug(dbg, 0, "%*sClient version: %d", level+1, "", pdu->u.handshake.client_hello->clientversion);
  801. debug(dbg, 0, "%*sRandom:", level+1, "");
  802. dump_random(dbg, level+2,
  803. pdu->u.handshake.client_hello->random);
  804. debug(dbg, 0, "%*sSessionId: ", level, "");
  805. octstr_dump(pdu->u.handshake.client_hello->session_id, level + 2);
  806. /* pack the list of keys */
  807. debug(dbg, 0, "%*sClient Key IDs: ", level+1, "");
  808. dump_key_list(dbg, level+2,
  809. pdu->u.handshake.client_hello->client_key_ids);
  810. debug(dbg, 0, "%*sTrusted Key IDs: ", level+1, "");
  811. dump_key_list(dbg, level+2,
  812. pdu->u.handshake.client_hello->trusted_key_ids);
  813. /* pack the list of CipherSuites */
  814. debug(dbg, 0, "%*sCipherSuite List: ", level+1, "");
  815. dump_ciphersuite_list(dbg, level+2,
  816. pdu->u.handshake.client_hello->ciphersuites);
  817. /* CompressionMethods */
  818. debug(dbg, 0, "%*sCompression Method List: ", level+1, "");
  819. dump_compression_method_list(dbg, level+2,
  820. pdu->u.handshake.client_hello->comp_methods);
  821. debug(dbg, 0, "%*sSeq Number Mode: %d", level+1, "", pdu->u.handshake.client_hello->snmode);
  822. debug(dbg, 0, "%*sKey Refresh: %p", level+1, "", pdu->u.handshake.client_hello->krefresh);
  823. break;
  824. case server_hello:
  825. debug(dbg, 0, "%*sServerHello :", level, "");
  826. debug(dbg, 0, "%*sServer version: %d", level+1, "", pdu->u.handshake.server_hello->serverversion);
  827. debug(dbg, 0, "%*sRandom:", level+1, "");
  828. dump_random(dbg, level+2,
  829. pdu->u.handshake.server_hello->random);
  830. debug(dbg, 0, "%*sSession ID: %d", level+1, "", pdu->u.handshake.server_hello->session_id);
  831. debug(dbg, 0, "%*sClient Key ID: %p", level+1, "", pdu->u.handshake.server_hello->client_key_id);
  832. /* CypherSuite */
  833. debug(dbg, 0, "%*sBulk Cipher Algo: %p", level+1, "", pdu->u.handshake.server_hello->ciphersuite->bulk_cipher_algo);
  834. debug(dbg, 0, "%*sMAC Algo: %p", level+1, "", pdu->u.handshake.server_hello->ciphersuite->mac_algo);
  835. /* CompressionMethod */
  836. debug(dbg, 0, "%*sCompression Method: %p", level+1, "", pdu->u.handshake.server_hello->comp_method);
  837. debug(dbg, 0, "%*sSeq Number Mode: %p", level+1, "", pdu->u.handshake.server_hello->snmode);
  838. debug(dbg, 0, "%*sKey Refresh: %p", level+1, "", pdu->u.handshake.server_hello->krefresh);
  839. break;
  840. case certificate:
  841. debug(dbg, 0, "%*sCertificate :", level, "");
  842. debug(dbg, 0, "%*sCertificate Format: %p", level+1, "", pdu->u.handshake.certificate->certificateformat);
  843. switch (pdu->u.handshake.certificate->certificateformat) {
  844. case WTLSCert:
  845. debug(dbg, 0, "%*sWTLS Certificate: %p", level+1, "");
  846. dump_wtls_certificate(dbg, level+2, pdu->u.handshake.certificate->wtls_certificate);
  847. break;
  848. case X509Cert:
  849. debug(dbg, 0, "%*sX509 Certificate: %p", level+1, "");
  850. octstr_dump(pdu->u.handshake.certificate->x509_certificate, level+2);
  851. break;
  852. case X968Cert:
  853. debug(dbg, 0, "%*sX968 Certificate: %p", level+1, "");
  854. octstr_dump(pdu->u.handshake.certificate->x968_certificate, level+2);
  855. break;
  856. }
  857. break;
  858. case server_key_exchange:
  859. debug(dbg, 0, "%*sServerKeyExchange :", level, "");
  860. /* ParameterSpecifier */
  861. debug(dbg, 0, "%*sParameter Index: %p", level+1, "", pdu->u.handshake.server_key_exchange->param_spec->param_index);
  862. if(pdu->u.handshake.server_key_exchange->param_spec->param_index == 255) {
  863. /* ParameterSet */
  864. debug(dbg, 0, "%*sParameter Set: %p", level+1, "", pdu->u.handshake.server_key_exchange->param_spec->param_set);
  865. }
  866. switch (client_key_exchange_algo) {
  867. case rsa_anon:
  868. dump_rsa_pubkey(dbg, level+1, pdu->u.handshake.server_key_exchange->rsa_params);
  869. break;
  870. case dh_anon:
  871. dump_dh_pubkey(dbg, level+1, pdu->u.handshake.server_key_exchange->dh_params);
  872. break;
  873. case ecdh_anon:
  874. dump_ec_pubkey(dbg, level+1, pdu->u.handshake.server_key_exchange->ecdh_params);
  875. break;
  876. }
  877. break;
  878. case client_key_exchange:
  879. debug(dbg, 0, "%*sClientKeyExchange :", level, "");
  880. switch (client_key_exchange_algo) {
  881. case rsa:
  882. case rsa_anon:
  883. dump_rsa_encrypted_secret(dbg, level+1, pdu->u.handshake.client_key_exchange->rsa_params);
  884. break;
  885. case dh_anon:
  886. dump_dh_pubkey(dbg, level+1, pdu->u.handshake.client_key_exchange->dh_anon_params);
  887. break;
  888. case ecdh_anon:
  889. case ecdh_ecdsa:
  890. dump_ec_pubkey(dbg, level+1, pdu->u.handshake.client_key_exchange->ecdh_params);
  891. break;
  892. }
  893. break;
  894. case server_hello_done:
  895. debug(dbg, 0, "%*sClientHelloDone.", level, "");
  896. /* empty */
  897. break;
  898. case finished:
  899. debug(dbg, 0, "%*sFinished :", level, "");
  900. debug(dbg, 0, "%*sverify_data :", level+1, "");
  901. octstr_dump(pdu->u.handshake.finished->verify_data, level+2);
  902. break;
  903. }
  904. break;
  905. case Application_PDU:
  906. debug(dbg, 0, "%*sApplication :", level, "");
  907. /* application message */
  908. octstr_dump(pdu->u.application.data, level+1);
  909. break;
  910. default:
  911. debug(dbg, 0, "%*sWTLS PDU at %p:", level, "", (void *)pdu);
  912. debug(dbg, 0, "%*s unknown type %u", level, "", pdu->type);
  913. }
  914. }
  915. #endif