1 /* ====================================================================
2 * The Kannel Software License, Version 1.0
3 *
4 * Copyright (c) 2001-2014 Kannel Group
5 * Copyright (c) 1998-2001 WapIT Ltd.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution,
21 * if any, must include the following acknowledgment:
22 * "This product includes software developed by the
23 * Kannel Group (http://www.kannel.org/)."
24 * Alternately, this acknowledgment may appear in the software itself,
25 * if and wherever such third-party acknowledgments normally appear.
26 *
27 * 4. The names "Kannel" and "Kannel Group" must not be used to
28 * endorse or promote products derived from this software without
29 * prior written permission. For written permission, please
30 * contact org@kannel.org.
31 *
32 * 5. Products derived from this software may not be called "Kannel",
33 * nor may "Kannel" appear in their name, without prior written
34 * permission of the Kannel Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Kannel Group. For more information on
51 * the Kannel Group, please see <http://www.kannel.org/>.
52 *
53 * Portions of this software are based upon software originally written at
54 * WapIT Ltd., Helsinki, Finland for the Kannel project.
55 */
56
57 /*
58 * wtls_pdu.c: pack and unpack WTLS packets
59 *
60 * Generates packing and unpacking code from wtls_pdu.def.
61 *
62 * Nikos Balkanas, Inaccess Networks (2009)
63 *
64 */
65
66 #include "gwlib/gwlib.h"
67
68 #ifdef HAVE_WTLS_OPENSSL
69
70 #include "gwlib/octstr.h"
71 #include "wtls_pdu.h"
72 #include "wtls_pdusupport.h"
73 #include "wtls_statesupport.h"
74
75 KeyExchangeSuite client_key_exchange_algo = rsa_anon;
76 PublicKeyAlgorithm public_key_algo;
77 SignatureAlgorithm signature_algo;
78
79 /* Function prototypes */
80 wtls_Payload *wtls_payload_unpack_from_offset(Octstr * data, int *offset);
81 int wtls_payload_guess_length(Octstr * data);
82
wtls_pdu_create(int type)83 wtls_PDU *wtls_pdu_create(int type)
84 {
85 wtls_PDU *pdu;
86
87 pdu = gw_malloc(sizeof(*pdu));
88 pdu->type = type;
89 pdu->reserved = 0;
90 pdu->cipher = 0;
91 pdu->snMode = 0;
92 pdu->seqNum = -1;
93 pdu->rlen = 0;
94
95 switch (pdu->type) {
96 case ChangeCipher_PDU:
97 pdu->u.cc.change = 1;
98 break;
99 case Alert_PDU:
100 pdu->u.alert.level = 0;
101 pdu->u.alert.desc = 0;
102 pdu->u.alert.chksum = 0;
103 break;
104 case Handshake_PDU:
105 pdu->u.handshake.msg_type = 0;
106 pdu->u.handshake.length = 0;
107 break;
108 case Application_PDU:
109 pdu->u.application.data = NULL;
110 break;
111 default:
112 warning(0, "Cannot create unknown WTLS PDU type %d", pdu->type);
113 break;
114 }
115
116 return pdu;
117 }
118
wtls_payload_destroy(wtls_Payload * payload)119 void wtls_payload_destroy(wtls_Payload * payload)
120 {
121 octstr_destroy(payload->data);
122 gw_free(payload);
123 }
124
wtls_pldList_destroy(List * pld_list)125 void wtls_pldList_destroy(List * pld_list)
126 {
127 gwlist_destroy(pld_list, (void *)wtls_payload_destroy);
128 }
129
wtls_pdu_destroy(wtls_PDU * pdu)130 void wtls_pdu_destroy(wtls_PDU * pdu)
131 {
132 if (pdu == NULL)
133 return;
134
135 switch (pdu->type) {
136 case ChangeCipher_PDU:
137 /* no memory was allocated for ChangeCipher_PDU */
138 break;
139 case Alert_PDU:
140 octstr_destroy(pdu->u.alert.chksum);
141 break;
142 case Handshake_PDU:
143 switch (pdu->u.handshake.msg_type) {
144 case hello_request:
145 break;
146 case client_hello:
147 destroy_random(pdu->u.handshake.client_hello->random);
148 octstr_destroy(pdu->u.handshake.client_hello->
149 session_id);
150 destroy_key_list(pdu->u.handshake.client_hello->
151 client_key_ids);
152 destroy_key_list(pdu->u.handshake.client_hello->
153 trusted_key_ids);
154 destroy_ciphersuite_list(pdu->u.handshake.client_hello->
155 ciphersuites);
156 destroy_compression_method_list(pdu->u.handshake.
157 client_hello->
158 comp_methods);
159 /* destroy the client_hello struct */
160 gw_free(pdu->u.handshake.client_hello);
161 break;
162 case server_hello:
163 destroy_random(pdu->u.handshake.server_hello->random);
164 octstr_destroy(pdu->u.handshake.server_hello->
165 session_id);
166 /* destroy the server_hello struct */
167 gw_free(pdu->u.handshake.server_hello);
168 break;
169 case certificate:
170 {
171 Certificate *cert;
172 List *certList =
173 pdu->u.handshake.certificates->certList;
174
175 for (;;) {
176 cert = gwlist_consume(certList);
177 if (!cert)
178 break;
179 switch (cert->certificateformat) {
180 case WTLSCert:
181 destroy_wtls_certificate(cert->
182 wtls_certificate);
183 break;
184
185 case X509Cert:
186 octstr_destroy(cert->
187 x509_certificate);
188 break;
189
190 case X968Cert:
191 octstr_destroy(cert->
192 x968_certificate);
193 break;
194 }
195 gw_free(cert);
196 }
197 gwlist_destroy(pdu->u.handshake.certificates->
198 certList, NULL);
199 }
200 break;
201
202 case server_key_exchange:
203 destroy_param_spec(pdu->u.handshake.
204 server_key_exchange->param_spec);
205 switch (client_key_exchange_algo) {
206 case rsa_anon:
207 destroy_rsa_pubkey(pdu->u.handshake.
208 server_key_exchange->
209 rsa_params);
210 break;
211 case dh_anon:
212 destroy_dh_pubkey(pdu->u.handshake.
213 server_key_exchange->
214 dh_params);
215 break;
216 case ecdh_anon:
217 destroy_ec_pubkey(pdu->u.handshake.
218 server_key_exchange->
219 ecdh_params);
220 break;
221 default:
222 break;
223 }
224 gw_free(pdu->u.handshake.server_key_exchange);
225 break;
226 case client_key_exchange:
227 switch (client_key_exchange_algo) {
228 case rsa:
229 case rsa_anon:
230 destroy_rsa_encrypted_secret(pdu->u.handshake.
231 client_key_exchange->
232 rsa_params);
233 break;
234 case dh_anon:
235 destroy_dh_pubkey(pdu->u.handshake.
236 client_key_exchange->
237 dh_anon_params);
238 break;
239 case ecdh_anon:
240 case ecdh_ecdsa:
241 destroy_ec_pubkey(pdu->u.handshake.
242 client_key_exchange->
243 ecdh_params);
244 break;
245 default:
246 break;
247 }
248 gw_free(pdu->u.handshake.client_key_exchange);
249 break;
250 case server_hello_done:
251 /* nothing to do here */
252 default:
253 break;
254 }
255 break;
256 case Application_PDU:
257 octstr_destroy(pdu->u.application.data);
258 break;
259 }
260
261 gw_free(pdu);
262 }
263
264 /* This function will pack a list of WTLS PDUs into a single Octstr, and return
265 that Octstr. */
wtls_pack_payloadlist(List * payloadlist,int seqnum)266 Octstr *wtls_pack_payloadlist(List * payloadlist, int seqnum)
267 {
268
269 Octstr *returnData = 0, *tempData1 = 0, *tempData2 = 0;
270 wtls_Payload *retrievedPDU;
271
272 /* Assert that our payloadlist is not NULL */
273 gw_assert(payloadlist != NULL);
274
275 /* Initialise our return Octstr */
276 returnData = octstr_create("");
277
278 /* While there are PDUs remaining in our list */
279 while (gwlist_len(payloadlist) > 0) {
280 /* Retrieve the next payload from the payloadlist */
281 retrievedPDU =
282 (wtls_Payload *) gwlist_extract_first(payloadlist);
283
284 /* Pack the PDU */
285 tempData2 = wtls_payload_pack(retrievedPDU, seqnum++);
286
287 /* Shift the current stuff in returnData to a temporary pointer */
288 tempData1 = returnData;
289
290 /* Tack it onto our Octstr */
291 returnData = octstr_cat(tempData1, tempData2);
292
293 /* And now, we can get rid of both tempData1 and tempData2 */
294 octstr_destroy(tempData1);
295 octstr_destroy(tempData2);
296 }
297
298 /* Is the Octstr we finish with of length > 0? */
299 if (octstr_len(returnData) > 0) {
300 /* Return the Octstr */
301 return returnData;
302 }
303
304 /* Otherwise, return NULL */
305 return NULL;
306 }
307
308 /* This function will unpack an Octstr and return a list of all PDUs contained
309 within that Octstr. If the contents of the packet are garbled in some fashion,
310 and one packet fails to be decoded correctly, we will continue regardless, and
311 a partial list will be returned. NULL is returned if no PDUs can be successfully
312 decoded from the supplied data */
wtls_unpack_payloadlist(Octstr * data)313 List *wtls_unpack_payloadlist(Octstr * data)
314 {
315
316 List *payloadlist = NULL;
317 int offset = 0;
318 int dataLength = 0;
319 wtls_Payload *tempPayload;
320
321 /* Has somebody passed in an unpack of a null pointer ? */
322 gw_assert(data != NULL);
323
324 /* Initialise our list */
325 payloadlist = gwlist_create();
326 dataLength = octstr_len(data);
327
328 /* While offset is less than the size of the data */
329 while (offset < dataLength) {
330
331 debug("wtls:wtls_unpack_payloadlist", 0, "Offset is now : %d",
332 offset);
333 /* Unpack from the supplied offset. This will bump up the value of offset */
334 tempPayload = wtls_payload_unpack_from_offset(data, &offset);
335
336 /* If the packet returned is not NULL */
337 if (tempPayload != NULL) {
338 /* Add the returned packet to the current list of packets */
339 gwlist_append(payloadlist, (void *)tempPayload);
340 }
341 }
342
343 debug("wtls:wtls_unpack_payloadlist", 0, "Finished, found %ld PDUs",
344 gwlist_len(payloadlist));
345
346 /* If the length of the list is greater than 0 */
347 if (gwlist_len(payloadlist) > 0) {
348 /* Return the List */
349 return payloadlist;
350 }
351
352 /* Otherwise return NULL */
353 return NULL;
354 }
355
356 /* This function tries to determine the length of the PDU at the start of the
357 supplied Octstr using (somewhat) intelligent means. If the packet is screwed
358 up in some fashion, returns length -1. Returns an int. */
359
wtls_payload_guess_length(Octstr * data)360 int wtls_payload_guess_length(Octstr * data)
361 {
362
363 int type = 0, lengthFlag = 0, lengthSize = 0, pdu_length = 0;
364 long lengthOffset = 1;
365
366 /* Is the fragment length indicator on? */
367 lengthFlag = octstr_get_bits(data, 0, 1);
368 if (lengthFlag) {
369 lengthSize = 2;
370 }
371
372 /* Is the sequence number indicator on? */
373 if (octstr_get_bits(data, 1, 1)) {
374 /* Yes, so hop over two extra bytes when reading the length */
375 lengthOffset += 2;
376 }
377 /* the message type */
378 type = octstr_get_bits(data, 4, 4);
379
380 /* If fragment length is turned on, jump to the necessary spot */
381 if (lengthFlag == 1) {
382 /* After this, lengthOffset + pdu_length == the total length of the PDU */
383 pdu_length = unpack_int16(data, &lengthOffset);
384 }
385
386 /* Oh great, so it's not switched on. How considerate. We'll have to make
387 a reasonable guess as to what it might be. */
388 else {
389 switch (type) {
390 case ChangeCipher_PDU:
391 /* They're really short */
392 pdu_length = 1;
393 break;
394
395 case Alert_PDU:
396 /* They're a bit longer */
397 pdu_length = 6;
398 break;
399
400 default:
401 /* Otherwise just give up and play dead */
402 pdu_length = -1;
403 break;
404 }
405 }
406
407 /* And that's the length of the contents, now just add the other doodads on */
408 if (pdu_length == -1) {
409 return -1;
410 } else {
411 /* The pdu length, plus the sequence number, plus the length of the length value,
412 plus the actual header byte */
413 return (pdu_length + lengthOffset);
414 }
415 }
416
417 /* This function will unpack an Octstr, starting at the specified offset, and
418 return the corresponding wtls_PDU* which was generated from that offset. Offset
419 is changed during the running of this function, and ends up as the octet at the start of the
420 next pdu */
421
wtls_payload_unpack_from_offset(Octstr * data,int * offset)422 wtls_Payload *wtls_payload_unpack_from_offset(Octstr * data, int *offset)
423 {
424 int guessedPayloadLength = 0;
425 int dataLength = 0;
426 Octstr *dataFromOffset = 0;
427 Octstr *dataFromOffsetToLength = 0;
428 wtls_Payload *returnPayload = 0;
429
430 /* This would be a sure sign of trouble */
431 gw_assert(offset != NULL);
432 gw_assert(data != NULL);
433 gw_assert(octstr_len(data) >= *offset);
434
435 dataLength = octstr_len(data);
436
437 /* First, we need to figure out how long a PDU starting from
438 the specified offset is going to be. We need to peek quickly into the
439 PDU to check this */
440 dataFromOffset = octstr_copy(data, *offset, dataLength);
441 guessedPayloadLength = wtls_payload_guess_length(dataFromOffset);
442
443 /* Ooops. Something's wrong. This requested PDU is screwed up. */
444 if (guessedPayloadLength == -1) {
445 octstr_destroy(dataFromOffset);
446 *offset = dataLength;
447 return NULL;
448 }
449
450 /* Quit if we discover that the PDU length plus the requested offset is
451 larger than the length of the data supplied - this would mean that we
452 would overrun our data, and therefore something is corrupt in this PDU.
453 Set the offset as the data length, which will indicate we've gone as far
454 as we can */
455 if ((*offset + guessedPayloadLength) > dataLength) {
456 octstr_destroy(dataFromOffset);
457 *offset = dataLength;
458 return NULL;
459 }
460
461 /* If we pass that test, set offset to the correct return value */
462 *offset += guessedPayloadLength;
463
464 /* Copy the octstr again, so that we end up with an octstr containing
465 just the PDU we want */
466 dataFromOffsetToLength =
467 octstr_copy(dataFromOffset, 0, guessedPayloadLength);
468
469 /* Submit that octstr to the wtls_message_unpack function */
470 returnPayload = wtls_payload_unpack(dataFromOffsetToLength);
471
472 octstr_destroy(dataFromOffset);
473 return returnPayload;
474 }
475
wtls_payload_unpack(Octstr * data)476 wtls_Payload *wtls_payload_unpack(Octstr * data)
477 {
478 wtls_Payload *payload = NULL;
479 long bitpos = 0, charpos = 0;
480
481 gw_assert(data != NULL);
482
483 payload = gw_malloc(sizeof(wtls_Payload));
484
485 /* the record field length flag */
486 payload->rlen = octstr_get_bits(data, bitpos, 1);
487 bitpos += 1;
488 /* the sequence number flag */
489 payload->snMode = octstr_get_bits(data, bitpos, 1);
490 bitpos += 1;
491 /* the cipher usage flag */
492 payload->cipher = octstr_get_bits(data, bitpos, 1);
493 bitpos += 1;
494 /* the reserved bit */
495 payload->reserved = octstr_get_bits(data, bitpos, 1);
496 bitpos += 1;
497 /* the message type */
498 payload->type = octstr_get_bits(data, bitpos, 4);
499 bitpos += 4;
500 charpos += 1;
501
502 /* Get the sequence number if present */
503 if (payload->snMode)
504 payload->seqNum = unpack_int16(data, &charpos);
505
506 /* consume the WTLS plaintext length if present */
507 if (payload->rlen)
508 charpos += 2;
509
510 /* the part of data that has just been processed is not
511 * needed anymore. We delete it. What is left of data is
512 * the payload.
513 */
514 octstr_delete(data, 0, charpos);
515 payload->data = data;
516
517 return payload;
518 }
519
520 // Doesn't destroy input payload
wtls_pdu_unpack(wtls_Payload * payload,WTLSMachine * wtls_machine)521 wtls_PDU *wtls_pdu_unpack(wtls_Payload * payload, WTLSMachine * wtls_machine)
522 {
523 wtls_PDU *pdu = NULL;
524 Octstr *buffer;
525 long charpos = 0;
526
527 gw_assert(payload->data != NULL);
528
529 pdu = gw_malloc(sizeof(wtls_PDU));
530
531 pdu->type = payload->type;
532 pdu->reserved = payload->reserved;
533 pdu->cipher = payload->cipher;
534 pdu->snMode = payload->snMode;
535 pdu->seqNum = payload->seqNum;
536 pdu->rlen = payload->rlen;
537
538 /* is the PDU encrypted ? */
539 /*
540 if(pdu->cipher) {
541 buffer = wtls_decrypt(payload->data, wtls_machine);
542 }
543 else {
544 */
545 buffer = payload->data;
546 /*
547 }
548 */
549
550 switch (pdu->type) {
551 case ChangeCipher_PDU:
552 pdu->u.cc.change = octstr_get_char(buffer, charpos);
553 charpos += 1;
554 break;
555
556 case Alert_PDU:
557 pdu->u.alert.level = octstr_get_char(buffer, charpos);
558 charpos += 1;
559 pdu->u.alert.desc = octstr_get_char(buffer, charpos);
560 charpos += 1;
561 pdu->u.alert.chksum = unpack_octstr_fixed(buffer, &charpos, 4);
562 break;
563
564 case Handshake_PDU:
565 pdu->u.handshake.msg_type = octstr_get_char(buffer, charpos);
566 charpos += 1;
567 pdu->u.handshake.length = unpack_int16(buffer, &charpos);
568 switch (pdu->u.handshake.msg_type) {
569 case hello_request:
570 break;
571
572 case client_hello:
573 pdu->u.handshake.client_hello =
574 (ClientHello *) gw_malloc(sizeof(ClientHello));
575 pdu->u.handshake.client_hello->clientversion =
576 octstr_get_char(buffer, charpos);
577 charpos += 1;
578 pdu->u.handshake.client_hello->random =
579 unpack_random(buffer, &charpos);
580 pdu->u.handshake.client_hello->session_id =
581 unpack_octstr(buffer, &charpos);
582
583 /* Unpack the list of keys */
584 pdu->u.handshake.client_hello->client_key_ids =
585 unpack_key_list(buffer, &charpos);
586 pdu->u.handshake.client_hello->trusted_key_ids =
587 unpack_key_list(buffer, &charpos);
588
589 /* Unpack the list of CipherSuites */
590 pdu->u.handshake.client_hello->ciphersuites =
591 unpack_ciphersuite_list(buffer, &charpos);
592
593 /* CompressionMethods */
594 pdu->u.handshake.client_hello->comp_methods =
595 unpack_compression_method_list(buffer, &charpos);
596
597 pdu->u.handshake.client_hello->snmode =
598 octstr_get_char(buffer, charpos);
599 charpos += 1;
600 pdu->u.handshake.client_hello->krefresh =
601 octstr_get_char(buffer, charpos);
602 charpos += 1;
603 break;
604
605 case server_hello:
606 pdu->u.handshake.server_hello =
607 (ServerHello *) gw_malloc(sizeof(ServerHello));
608 pdu->u.handshake.server_hello->serverversion =
609 octstr_get_char(buffer, charpos);
610 charpos += 1;
611 pdu->u.handshake.server_hello->random =
612 unpack_random(buffer, &charpos);
613 pdu->u.handshake.server_hello->session_id =
614 unpack_octstr(buffer, &charpos);
615 pdu->u.handshake.server_hello->client_key_id =
616 octstr_get_char(buffer, charpos);
617 charpos += 1;
618 /* CypherSuite */
619 pdu->u.handshake.server_hello->ciphersuite->
620 bulk_cipher_algo = octstr_get_char(buffer, charpos);
621 charpos += 1;
622 pdu->u.handshake.server_hello->ciphersuite->mac_algo =
623 octstr_get_char(buffer, charpos);
624 charpos += 1;
625
626 /* CompressionMethod */
627 pdu->u.handshake.server_hello->comp_method =
628 octstr_get_char(buffer, charpos);
629 charpos += 1;
630
631 pdu->u.handshake.server_hello->snmode =
632 octstr_get_char(buffer, charpos);
633 charpos += 1;
634 pdu->u.handshake.server_hello->krefresh =
635 octstr_get_char(buffer, charpos);
636 charpos += 1;
637 break;
638
639 case certificate:
640 {
641 List *certList = gwlist_create();
642 Certificate *cert;
643 int len = unpack_int16(buffer, &charpos);
644
645 while (charpos <= len) {
646 cert =
647 (Certificate *)
648 gw_malloc(sizeof(Certificate));
649 cert->certificateformat =
650 octstr_get_char(buffer, charpos);
651 charpos += 1;
652 switch (cert->certificateformat) {
653 case WTLSCert:
654 cert->wtls_certificate =
655 unpack_wtls_certificate
656 (buffer, &charpos);
657 break;
658
659 case X509Cert:
660 cert->x509_certificate =
661 unpack_octstr16(buffer,
662 &charpos);
663 break;
664
665 case X968Cert:
666 cert->x968_certificate =
667 unpack_octstr16(buffer,
668 &charpos);
669 break;
670 }
671 gwlist_append(certList, cert);
672 }
673 pdu->u.handshake.certificates->certList =
674 certList;
675 }
676 break;
677
678 case server_key_exchange:
679 pdu->u.handshake.server_key_exchange =
680 (ServerKeyExchange *)
681 gw_malloc(sizeof(ServerKeyExchange));
682 /* unpack the ParameterSpecifier and ParameterSet */
683 pdu->u.handshake.server_key_exchange->param_spec =
684 unpack_param_spec(buffer, &charpos);
685 switch (client_key_exchange_algo) {
686 case rsa_anon:
687 pdu->u.handshake.server_key_exchange->
688 rsa_params =
689 unpack_rsa_pubkey(buffer, &charpos);
690 break;
691
692 case dh_anon:
693 pdu->u.handshake.server_key_exchange->
694 dh_params =
695 unpack_dh_pubkey(buffer, &charpos);
696 break;
697
698 case ecdh_anon:
699 pdu->u.handshake.server_key_exchange->
700 ecdh_params =
701 unpack_ec_pubkey(buffer, &charpos);
702 break;
703
704 default:
705 break;
706 }
707 break;
708
709 case client_key_exchange:
710 pdu->u.handshake.client_key_exchange =
711 (ClientKeyExchange *)
712 gw_malloc(sizeof(ClientKeyExchange));
713 switch (client_key_exchange_algo) {
714 case rsa:
715 case rsa_anon:
716 pdu->u.handshake.client_key_exchange->
717 rsa_params =
718 unpack_rsa_encrypted_secret(buffer,
719 &charpos);
720 break;
721
722 case dh_anon:
723 pdu->u.handshake.client_key_exchange->
724 dh_anon_params =
725 unpack_dh_pubkey(buffer, &charpos);
726 break;
727
728 case ecdh_anon:
729 case ecdh_ecdsa:
730 pdu->u.handshake.client_key_exchange->
731 ecdh_params =
732 unpack_ec_pubkey(buffer, &charpos);
733 break;
734
735 default:
736 break;
737 }
738 break;
739
740 case server_hello_done:
741 /* empty */
742 break;
743
744 case finished:
745 pdu->u.handshake.finished =
746 (Finished *) gw_malloc(sizeof(Finished));
747 pdu->u.handshake.finished->verify_data =
748 unpack_octstr_fixed(buffer, &charpos, 12);
749 octstr_dump(pdu->u.handshake.finished->verify_data, 0);
750 break;
751
752 default:
753 break;
754 }
755 break;
756
757 case Application_PDU:
758 /* application message */
759 pdu->u.application.data = octstr_duplicate(buffer);
760 break;
761
762 default:
763 debug("wap.wtls", 0, "%*sPDU: ", 0, "");
764 octstr_dump(buffer, 0);
765 panic(0, "Unpacking unknown WTLS PDU type %ld",
766 (long)pdu->type);
767 break;
768 }
769
770 return (pdu);
771 }
772
wtls_payload_pack(wtls_Payload * payload,int seqnum)773 Octstr *wtls_payload_pack(wtls_Payload * payload, int seqnum)
774 {
775 Octstr *data;
776 long bitpos, charpos;
777 long sizepos;
778
779 /* We rely on octstr_set_bits to lengthen our octstr as needed. */
780 data = octstr_create("");
781 bitpos = 0;
782 charpos = 0;
783 sizepos = 0;
784
785 /* the record field length flag - always present */
786 octstr_set_bits(data, bitpos, 1, 1);
787 bitpos += 1;
788 /* the sequence number flag */
789 octstr_set_bits(data, bitpos, 1, payload->snMode);
790 bitpos += 1;
791 /* the cipher usage flag */
792 octstr_set_bits(data, bitpos, 1, payload->cipher);
793 bitpos += 1;
794 /* the reserved bit */
795 octstr_set_bits(data, bitpos, 1, payload->reserved);
796 bitpos += 1;
797
798 /* set the message type */
799 octstr_set_bits(data, bitpos, 4, payload->type);
800 bitpos += 4;
801 charpos += 1;
802
803 /* set the sequence number */
804 if (payload->snMode)
805 charpos = pack_int16(data, charpos, seqnum);
806
807 /* set the WTLS length */
808 charpos = pack_int16(data, charpos, payload->rlen);
809
810 /* append the data from the wtls_PDU */
811 octstr_insert(data, payload->data, octstr_len(data));
812
813 return data;
814 }
815
wtls_pdu_pack(wtls_PDU * pdu,WTLSMachine * wtls_machine)816 wtls_Payload *wtls_pdu_pack(wtls_PDU * pdu, WTLSMachine * wtls_machine)
817 {
818 Octstr *buffer, *encryptedbuffer;
819 wtls_Payload *payload;
820 long bitpos, charpos;
821 long messageSizePos, sizepos;
822 /* Used for length calculations */
823 int size, recordType;
824
825 /* create the wtls_PDU */
826 payload = (wtls_Payload *) gw_malloc(sizeof(wtls_Payload));
827 payload->type = pdu->type;
828 payload->reserved = pdu->reserved;
829 payload->cipher = pdu->cipher;
830 payload->snMode = pdu->snMode;
831 payload->seqNum = pdu->seqNum;
832
833 /* We rely on octstr_set_bits to lengthen our octstr as needed. */
834 buffer = octstr_create("");
835 bitpos = 0;
836 charpos = 0;
837 sizepos = 0;
838
839 switch (pdu->type) {
840 case ChangeCipher_PDU:
841 octstr_append_char(buffer, pdu->u.cc.change);
842 charpos += 1;
843 break;
844 case Alert_PDU:
845 octstr_append_char(buffer, pdu->u.alert.level);
846 charpos += 1;
847 octstr_append_char(buffer, pdu->u.alert.desc);
848 charpos += 1;
849 charpos =
850 pack_octstr_fixed(buffer, charpos, pdu->u.alert.chksum);
851 break;
852 case Handshake_PDU:
853 octstr_append_char(buffer, pdu->u.handshake.msg_type);
854 charpos += 1;
855 /* Save the location of the message size */
856 messageSizePos = charpos;
857 charpos = pack_int16(buffer, charpos, pdu->u.handshake.length);
858 switch (pdu->u.handshake.msg_type) {
859 case hello_request:
860 break;
861 case client_hello:
862 octstr_append_char(buffer,
863 pdu->u.handshake.client_hello->
864 clientversion);
865 charpos += 1;
866 charpos =
867 pack_random(buffer, charpos,
868 pdu->u.handshake.client_hello->random);
869 charpos =
870 pack_octstr(buffer, charpos,
871 pdu->u.handshake.client_hello->
872 session_id);
873
874 /* pack the list of keys */
875 charpos = pack_key_list(buffer, charpos,
876 pdu->u.handshake.client_hello->
877 client_key_ids);
878 charpos =
879 pack_key_list(buffer, charpos,
880 pdu->u.handshake.client_hello->
881 trusted_key_ids);
882
883 /* pack the list of CipherSuites */
884 charpos = pack_ciphersuite_list(buffer, charpos,
885 pdu->u.handshake.
886 client_hello->
887 ciphersuites);
888
889 /* CompressionMethods */
890 charpos = pack_compression_method_list(buffer, charpos,
891 pdu->u.handshake.
892 client_hello->
893 comp_methods);
894
895 octstr_append_char(buffer,
896 pdu->u.handshake.client_hello->
897 snmode);
898 charpos += 1;
899 octstr_append_char(buffer,
900 pdu->u.handshake.client_hello->
901 krefresh);
902 charpos += 1;
903 break;
904 case server_hello:
905 octstr_append_char(buffer,
906 pdu->u.handshake.server_hello->
907 serverversion);
908 charpos += 1;
909 charpos =
910 pack_random(buffer, charpos,
911 pdu->u.handshake.server_hello->random);
912 charpos =
913 pack_octstr(buffer, charpos,
914 pdu->u.handshake.server_hello->
915 session_id);
916 octstr_append_char(buffer,
917 pdu->u.handshake.
918 server_hello->client_key_id);
919 charpos += 1;
920 /* CypherSuite */
921 octstr_append_char(buffer,
922 pdu->u.handshake.
923 server_hello->ciphersuite->
924 bulk_cipher_algo);
925 charpos += 1;
926 octstr_append_char(buffer,
927 pdu->u.handshake.
928 server_hello->ciphersuite->mac_algo);
929 charpos += 1;
930
931 /* CompressionMethod */
932 octstr_append_char(buffer,
933 pdu->u.handshake.server_hello->
934 comp_method);
935 charpos += 1;
936
937 octstr_append_char(buffer,
938 pdu->u.handshake.server_hello->
939 snmode);
940 charpos += 1;
941 octstr_append_char(buffer,
942 pdu->u.handshake.server_hello->
943 krefresh);
944 charpos += 1;
945
946 break;
947 case certificate:
948 {
949 Certificate *cert;
950 int pos = charpos, len;
951
952 charpos = pack_int16(buffer, charpos, 0);
953 for (;;) {
954 cert =
955 gwlist_consume(pdu->u.handshake.
956 certificates->
957 certList);
958 if (!cert)
959 break;
960 octstr_append_char(buffer,
961 cert->
962 certificateformat);
963 charpos += 1;
964 switch (cert->certificateformat) {
965 case WTLSCert:
966 charpos =
967 pack_wtls_certificate
968 (buffer, charpos,
969 cert->wtls_certificate);
970 destroy_wtls_certificate(cert->
971 wtls_certificate);
972 break;
973
974 case X509Cert:
975 charpos =
976 pack_octstr16(buffer,
977 charpos,
978 cert->
979 x509_certificate);
980 octstr_destroy(cert->
981 x509_certificate);
982 break;
983
984 case X968Cert:
985 charpos =
986 pack_octstr16(buffer,
987 charpos,
988 cert->
989 x968_certificate);
990 octstr_destroy(cert->
991 x968_certificate);
992 break;
993 }
994 gw_free(cert);
995 }
996 len = charpos - pos - 2;
997 octstr_set_char(buffer, pos,
998 (len & 0xFF00) >> 8);
999 octstr_set_char(buffer, pos + 1, len & 0xFF);
1000 }
1001 break;
1002 case server_key_exchange:
1003 debug("wtls: ", 0, "Packing ServerKeyExchange");
1004 /* pack the ParameterSpecifier */
1005 charpos =
1006 pack_param_spec(buffer, charpos,
1007 pdu->u.handshake.
1008 server_key_exchange->param_spec);
1009
1010 switch (client_key_exchange_algo) {
1011 case rsa_anon:
1012 charpos =
1013 pack_rsa_pubkey(buffer, charpos,
1014 pdu->u.handshake.
1015 server_key_exchange->
1016 rsa_params);
1017 break;
1018 case dh_anon:
1019 charpos =
1020 pack_dh_pubkey(buffer, charpos,
1021 pdu->u.handshake.
1022 server_key_exchange->
1023 dh_params);
1024 break;
1025 case ecdh_anon:
1026 charpos =
1027 pack_ec_pubkey(buffer, charpos,
1028 pdu->u.handshake.
1029 server_key_exchange->
1030 ecdh_params);
1031 break;
1032 default:
1033 break;
1034 }
1035 break;
1036 case client_key_exchange:
1037 switch (client_key_exchange_algo) {
1038 case rsa:
1039 case rsa_anon:
1040 charpos =
1041 pack_rsa_encrypted_secret(buffer, charpos,
1042 pdu->u.handshake.
1043 client_key_exchange->
1044 rsa_params);
1045 break;
1046 case dh_anon:
1047 charpos =
1048 pack_dh_pubkey(buffer, charpos,
1049 pdu->u.handshake.
1050 client_key_exchange->
1051 dh_anon_params);
1052 break;
1053 case ecdh_anon:
1054 case ecdh_ecdsa:
1055 charpos =
1056 pack_ec_pubkey(buffer, charpos,
1057 pdu->u.handshake.
1058 client_key_exchange->
1059 ecdh_params);
1060 break;
1061 default:
1062 break;
1063 }
1064 break;
1065 case server_hello_done:
1066 /* empty */
1067 default:
1068 break;
1069 case finished:
1070 charpos =
1071 pack_octstr_fixed(buffer, charpos,
1072 pdu->u.handshake.finished->
1073 verify_data);
1074 debug("wtls", 0, "verify_data (in pack)");
1075 octstr_dump(pdu->u.handshake.finished->verify_data, 0);
1076 break;
1077 }
1078 /* Change the length */
1079 size = octstr_len(buffer) - messageSizePos - 2;
1080 debug("wtls_msg.c:length", 0, "Setting msg size to : %d", size);
1081 octstr_set_char(buffer, messageSizePos, (size & 0xFF00) >> 8);
1082 messageSizePos += 1;
1083 octstr_set_char(buffer, messageSizePos, (size & 0x00FF));
1084
1085 /* we keep the handshake data to create the Finished PDU */
1086 octstr_append(wtls_machine->handshake_data, buffer);
1087 break;
1088
1089 case Application_PDU:
1090 /* application message */
1091 octstr_destroy(buffer);
1092 buffer = pdu->u.application.data;
1093 pdu->u.application.data = NULL;
1094 break;
1095
1096 default:
1097 panic(0, "Packing unknown WTLS PDU type %ld", (long)pdu->type);
1098 }
1099
1100 /* encrypt the buffer if needed */
1101 if (pdu->cipher) {
1102 /* the MAC is calculated with the record type so we need it now */
1103 recordType = 1 << 7; /* length, always present */
1104 recordType |= pdu->snMode << 6;
1105 recordType |= pdu->cipher << 5;
1106 recordType |= pdu->reserved << 4;
1107 recordType |= pdu->type;
1108 if (!(encryptedbuffer = wtls_encrypt(buffer, wtls_machine,
1109 recordType)))
1110 return (NULL);
1111
1112 payload->data = encryptedbuffer;
1113 } else
1114 payload->data = buffer;
1115
1116 payload->rlen = octstr_len(payload->data);
1117 debug("wtls", 0, "Packed PDU Length: %d", payload->rlen);
1118
1119 return (payload);
1120 }
1121
wtls_payload_dump(wtls_Payload * payload,int level)1122 void wtls_payload_dump(wtls_Payload * payload, int level)
1123 {
1124 char *dbg = "wap.wtls", type[20], *data;
1125 if (!payload)
1126 return;
1127 data = octstr_get_cstr(payload->data);
1128
1129 /* the message type */
1130 pduName(type, payload->type);
1131 debug(dbg, 0, "%*sPayload type: %s", level, "", type);
1132 if (payload->type == Handshake_PDU) {
1133 hsName(type, *data);
1134 debug(dbg, 0, "%*sHandshake type: %s", level + 1, "", type);
1135 } else if (payload->type == Alert_PDU) {
1136 alertName(type, *(data + 1));
1137 debug(dbg, 0, "%*sAlert type: %s", level + 1, "", type);
1138 }
1139 /* the reserved bit */
1140 debug(dbg, 0, "%*sReserved bit: %d", level, "", payload->reserved);
1141 /* cipher usage flag */
1142 debug(dbg, 0, "%*sCipher in use: %d", level, "", payload->cipher);
1143 /* the sequence number flag */
1144 debug(dbg, 0, "%*sSequence number in use: %d", level, "",
1145 payload->seqNum);
1146 /* the record field length flag */
1147 debug(dbg, 0, "%*sRecord field length present: %d", level, "",
1148 payload->rlen);
1149
1150 octstr_dump(payload->data, level + 1);
1151 }
1152
wtls_pdu_dump(wtls_PDU * pdu,int level)1153 void wtls_pdu_dump(wtls_PDU * pdu, int level)
1154 {
1155 char *dbg = "wap.wtls", type[20];
1156
1157 /* the message type */
1158 pduName(type, pdu->type);
1159 debug(dbg, 0, "%*sPDU type: %s", level, "", type);
1160 if (pdu->type == Handshake_PDU) {
1161 hsName(type, pdu->u.handshake.msg_type);
1162 debug(dbg, 0, "%*sHandshake type: %s", level + 1, "", type);
1163 }
1164 /* the reserved bit */
1165 debug(dbg, 0, "%*sReserved bit: %d", level, "", pdu->reserved);
1166 /* cipher usage flag */
1167 debug(dbg, 0, "%*sCipher in use: %d", level, "", pdu->cipher);
1168 /* the sequence number flag */
1169 debug(dbg, 0, "%*sSequence number in use: %d", level, "", pdu->seqNum);
1170 /* the record field length flag */
1171 debug(dbg, 0, "%*sRecord field length present: %d", level, "",
1172 pdu->rlen);
1173
1174 switch (pdu->type) {
1175 case ChangeCipher_PDU:
1176 debug(dbg, 0, "%*sChangeCipher:", level, "");
1177 debug(dbg, 0, "%*sChange: %d", level + 1, "", pdu->u.cc.change);
1178 break;
1179
1180 case Alert_PDU:
1181 debug(dbg, 0, "%*sAlert:", level, "");
1182 debug(dbg, 0, "%*sLevel: %d", level + 1, "",
1183 pdu->u.alert.level);
1184 debug(dbg, 0, "%*sDescription: %d", level + 1, "",
1185 pdu->u.alert.desc);
1186 debug(dbg, 0, "%*sChecksum: %s", level + 1, "",
1187 octstr_get_cstr(pdu->u.alert.chksum));
1188 break;
1189
1190 case Handshake_PDU:
1191 debug(dbg, 0, "%*sHandshake:", level, "");
1192 debug(dbg, 0, "%*sMessage Type: %d", level + 1, "",
1193 pdu->u.handshake.msg_type);
1194 debug(dbg, 0, "%*sLength: %d", level + 1, "",
1195 pdu->u.handshake.length);
1196 switch (pdu->u.handshake.msg_type) {
1197 case hello_request:
1198 debug(dbg, 0, "%*sHelloRequest.", level, "");
1199 break;
1200
1201 case client_hello:
1202 debug(dbg, 0, "%*sClientHello:", level, "");
1203 debug(dbg, 0, "%*sClient version: %d", level + 1, "",
1204 pdu->u.handshake.client_hello->clientversion);
1205 debug(dbg, 0, "%*sRandom:", level + 1, "");
1206 dump_random(dbg, level + 2,
1207 pdu->u.handshake.client_hello->random);
1208 debug(dbg, 0, "%*sSessionId: ", level, "");
1209 octstr_dump(pdu->u.handshake.client_hello->session_id,
1210 level + 2);
1211 /* pack the list of keys */
1212 debug(dbg, 0, "%*sClient Key IDs: ", level + 1, "");
1213 dump_key_list(dbg, level + 2,
1214 pdu->u.handshake.client_hello->
1215 client_key_ids);
1216 debug(dbg, 0, "%*sTrusted Key IDs: ", level + 1, "");
1217 dump_key_list(dbg, level + 2,
1218 pdu->u.handshake.client_hello->
1219 trusted_key_ids);
1220 /* pack the list of CipherSuites */
1221 debug(dbg, 0, "%*sCipherSuite List: ", level + 1, "");
1222 dump_ciphersuite_list(dbg, level + 2,
1223 pdu->u.handshake.client_hello->
1224 ciphersuites);
1225 /* CompressionMethods */
1226 debug(dbg, 0, "%*sCompression Method List: ", level + 1,
1227 "");
1228 dump_compression_method_list(dbg, level + 2,
1229 pdu->u.handshake.
1230 client_hello->
1231 comp_methods);
1232 debug(dbg, 0, "%*sSeq Number Mode: %d", level + 1, "",
1233 pdu->u.handshake.client_hello->snmode);
1234 debug(dbg, 0, "%*sKey Refresh: %d", level + 1, "",
1235 pdu->u.handshake.client_hello->krefresh);
1236 break;
1237
1238 case server_hello:
1239 debug(dbg, 0, "%*sServerHello:", level, "");
1240 debug(dbg, 0, "%*sServer version: %d", level + 1, "",
1241 pdu->u.handshake.server_hello->serverversion);
1242 debug(dbg, 0, "%*sRandom:", level + 1, "");
1243 dump_random(dbg, level + 2,
1244 pdu->u.handshake.server_hello->random);
1245 debug(dbg, 0, "%*sSession ID: %s", level + 1, "",
1246 octstr_get_cstr(pdu->u.handshake.
1247 server_hello->session_id));
1248 debug(dbg, 0, "%*sClient Key ID: %d", level + 1, "",
1249 pdu->u.handshake.server_hello->client_key_id);
1250 /* CypherSuite */
1251 debug(dbg, 0, "%*sBulk Cipher Algo: %d", level + 1, "",
1252 pdu->u.handshake.server_hello->
1253 ciphersuite->bulk_cipher_algo);
1254 debug(dbg, 0, "%*sMAC Algo: %d", level + 1, "",
1255 pdu->u.handshake.server_hello->ciphersuite->
1256 mac_algo);
1257 /* CompressionMethod */
1258 debug(dbg, 0, "%*sCompression Method: %d", level + 1,
1259 "", pdu->u.handshake.server_hello->comp_method);
1260 debug(dbg, 0, "%*sSeq Number Mode: %d", level + 1, "",
1261 pdu->u.handshake.server_hello->snmode);
1262 debug(dbg, 0, "%*sKey Refresh: %d", level + 1, "",
1263 pdu->u.handshake.server_hello->krefresh);
1264 break;
1265
1266 case certificate:
1267 debug(dbg, 0, "%*sCertificate:", level, "");
1268 {
1269 Certificate *cert;
1270 List *certList =
1271 pdu->u.handshake.certificates->certList;
1272 int i = 0, len = gwlist_len(certList);
1273
1274 for (; i < len; i++) {
1275 cert = gwlist_get(certList, i);
1276
1277 debug(dbg, 0,
1278 "%*sCertificate Format: %d",
1279 level + 1, "",
1280 cert->certificateformat);
1281 switch (cert->certificateformat) {
1282 case WTLSCert:
1283 debug(dbg, 0,
1284 "%*sWTLS Certificate:",
1285 level + 1, "");
1286 dump_wtls_certificate(dbg,
1287 level + 2,
1288 cert->
1289 wtls_certificate);
1290 break;
1291
1292 case X509Cert:
1293 debug(dbg, 0,
1294 "%*sX509 Certificate:",
1295 level + 1, "");
1296 octstr_dump(cert->
1297 x509_certificate,
1298 level + 2);
1299 break;
1300
1301 case X968Cert:
1302 debug(dbg, 0,
1303 "%*sX968 Certificate:",
1304 level + 1, "");
1305 octstr_dump(cert->
1306 x968_certificate,
1307 level + 2);
1308 break;
1309 }
1310 }
1311 }
1312 break;
1313
1314 case server_key_exchange:
1315 debug(dbg, 0, "%*sServerKeyExchange: ", level, "");
1316 /* ParameterSpecifier */
1317 debug(dbg, 0, "%*sParameter Index: %d", level + 1, "",
1318 pdu->u.handshake.server_key_exchange->
1319 param_spec->param_index);
1320 if (pdu->u.handshake.server_key_exchange->
1321 param_spec->param_index == 255) {
1322 /* ParameterSet */
1323 debug(dbg, 0, "%*sParameter Set: %p", level + 1,
1324 "",
1325 pdu->u.handshake.server_key_exchange->
1326 param_spec->param_set);
1327 }
1328 switch (client_key_exchange_algo) {
1329 case rsa_anon:
1330 dump_rsa_pubkey(dbg, level + 1,
1331 pdu->u.handshake.
1332 server_key_exchange->
1333 rsa_params);
1334 break;
1335
1336 case dh_anon:
1337 dump_dh_pubkey(dbg, level + 1,
1338 pdu->u.handshake.
1339 server_key_exchange->dh_params);
1340 break;
1341
1342 case ecdh_anon:
1343 dump_ec_pubkey(dbg, level + 1,
1344 pdu->u.handshake.
1345 server_key_exchange->
1346 ecdh_params);
1347 break;
1348
1349 default:
1350 break;
1351 }
1352 break;
1353
1354 case client_key_exchange:
1355 debug(dbg, 0, "%*sClientKeyExchange:", level, "");
1356 switch (client_key_exchange_algo) {
1357 case rsa:
1358 case rsa_anon:
1359 dump_rsa_encrypted_secret(dbg, level + 1,
1360 pdu->u.handshake.
1361 client_key_exchange->
1362 rsa_params);
1363 break;
1364
1365 case dh_anon:
1366 dump_dh_pubkey(dbg, level + 1,
1367 pdu->u.handshake.
1368 client_key_exchange->
1369 dh_anon_params);
1370 break;
1371
1372 case ecdh_anon:
1373 case ecdh_ecdsa:
1374 dump_ec_pubkey(dbg, level + 1,
1375 pdu->u.handshake.
1376 client_key_exchange->
1377 ecdh_params);
1378 break;
1379
1380 default:
1381 break;
1382 }
1383 break;
1384
1385 case server_hello_done:
1386 debug(dbg, 0, "%*sClientHelloDone.", level, "");
1387 /* empty */
1388 break;
1389
1390 case finished:
1391 debug(dbg, 0, "%*sFinished:", level, "");
1392 debug(dbg, 0, "%*sverify_data :", level + 1, "");
1393 octstr_dump(pdu->u.handshake.finished->verify_data,
1394 level + 2);
1395 break;
1396
1397 default:
1398 break;
1399 }
1400 break;
1401
1402 case Application_PDU:
1403 debug(dbg, 0, "%*sApplication:", level, "");
1404 /* application message */
1405 octstr_dump(pdu->u.application.data, level + 1);
1406 break;
1407
1408 default:
1409 debug(dbg, 0, "%*sWTLS PDU at %p:", level, "", (void *)pdu);
1410 debug(dbg, 0, "%*s unknown type %u", level, "", pdu->type);
1411 }
1412 }
1413 #endif /* HAVE_WTLS_OPENSSL */
1414