~ubuntu-branches/ubuntu/lucid/openssl/lucid-proposed

« back to all changes in this revision

Viewing changes to ssl/t1_lib.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-06-13 18:15:46 UTC
  • mto: (11.1.5 squeeze)
  • mto: This revision was merged to the branch mainline in revision 34.
  • Revision ID: james.westby@ubuntu.com-20090613181546-vbfntai3b009dl1u
Tags: upstream-0.9.8k
ImportĀ upstreamĀ versionĀ 0.9.8k

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
#include <openssl/objects.h>
61
61
#include <openssl/evp.h>
62
62
#include <openssl/hmac.h>
 
63
#include <openssl/ocsp.h>
63
64
#include "ssl_locl.h"
64
65
 
65
66
const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
190
191
                        }
191
192
                }
192
193
 
 
194
        if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
 
195
                {
 
196
                int i;
 
197
                long extlen, idlen, itmp;
 
198
                OCSP_RESPID *id;
 
199
 
 
200
                idlen = 0;
 
201
                for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
 
202
                        {
 
203
                        id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
 
204
                        itmp = i2d_OCSP_RESPID(id, NULL);
 
205
                        if (itmp <= 0)
 
206
                                return NULL;
 
207
                        idlen += itmp + 2;
 
208
                        }
 
209
 
 
210
                if (s->tlsext_ocsp_exts)
 
211
                        {
 
212
                        extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
 
213
                        if (extlen < 0)
 
214
                                return NULL;
 
215
                        }
 
216
                else
 
217
                        extlen = 0;
 
218
                        
 
219
                if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL;
 
220
                s2n(TLSEXT_TYPE_status_request, ret);
 
221
                if (extlen + idlen > 0xFFF0)
 
222
                        return NULL;
 
223
                s2n(extlen + idlen + 5, ret);
 
224
                *(ret++) = TLSEXT_STATUSTYPE_ocsp;
 
225
                s2n(idlen, ret);
 
226
                for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
 
227
                        {
 
228
                        /* save position of id len */
 
229
                        unsigned char *q = ret;
 
230
                        id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
 
231
                        /* skip over id len */
 
232
                        ret += 2;
 
233
                        itmp = i2d_OCSP_RESPID(id, &ret);
 
234
                        /* write id len */
 
235
                        s2n(itmp, q);
 
236
                        }
 
237
                s2n(extlen, ret);
 
238
                if (extlen > 0)
 
239
                        i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
 
240
                }
 
241
 
193
242
        if ((extdatalen = ret-p-2)== 0) 
194
243
                return p;
195
244
 
220
269
                s2n(TLSEXT_TYPE_session_ticket,ret);
221
270
                s2n(0,ret);
222
271
                }
223
 
                
 
272
 
 
273
        if (s->tlsext_status_expected)
 
274
                { 
 
275
                if ((long)(limit - ret - 4) < 0) return NULL; 
 
276
                s2n(TLSEXT_TYPE_status_request,ret);
 
277
                s2n(0,ret);
 
278
                }
 
279
 
224
280
        if ((extdatalen = ret-p-2)== 0) 
225
281
                return p;
226
282
 
235
291
        unsigned short len;
236
292
        unsigned char *data = *p;
237
293
        s->servername_done = 0;
 
294
        s->tlsext_status_type = -1;
238
295
 
239
296
        if (data >= (d+n-2))
240
297
                return 1;
324
381
                                                s->session->tlsext_hostname[len]='\0';
325
382
                                                if (strlen(s->session->tlsext_hostname) != len) {
326
383
                                                        OPENSSL_free(s->session->tlsext_hostname);
 
384
                                                        s->session->tlsext_hostname = NULL;
327
385
                                                        *al = TLS1_AD_UNRECOGNIZED_NAME;
328
386
                                                        return 0;
329
387
                                                }
349
407
                                }
350
408
 
351
409
                        }
 
410
                else if (type == TLSEXT_TYPE_status_request
 
411
                                                && s->ctx->tlsext_status_cb)
 
412
                        {
 
413
                
 
414
                        if (size < 5) 
 
415
                                {
 
416
                                *al = SSL_AD_DECODE_ERROR;
 
417
                                return 0;
 
418
                                }
 
419
 
 
420
                        s->tlsext_status_type = *data++;
 
421
                        size--;
 
422
                        if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
 
423
                                {
 
424
                                const unsigned char *sdata;
 
425
                                int dsize;
 
426
                                /* Read in responder_id_list */
 
427
                                n2s(data,dsize);
 
428
                                size -= 2;
 
429
                                if (dsize > size  ) 
 
430
                                        {
 
431
                                        *al = SSL_AD_DECODE_ERROR;
 
432
                                        return 0;
 
433
                                        }
 
434
                                while (dsize > 0)
 
435
                                        {
 
436
                                        OCSP_RESPID *id;
 
437
                                        int idsize;
 
438
                                        if (dsize < 4)
 
439
                                                {
 
440
                                                *al = SSL_AD_DECODE_ERROR;
 
441
                                                return 0;
 
442
                                                }
 
443
                                        n2s(data, idsize);
 
444
                                        dsize -= 2 + idsize;
 
445
                                        if (dsize < 0)
 
446
                                                {
 
447
                                                *al = SSL_AD_DECODE_ERROR;
 
448
                                                return 0;
 
449
                                                }
 
450
                                        sdata = data;
 
451
                                        data += idsize;
 
452
                                        id = d2i_OCSP_RESPID(NULL,
 
453
                                                                &sdata, idsize);
 
454
                                        if (!id)
 
455
                                                {
 
456
                                                *al = SSL_AD_DECODE_ERROR;
 
457
                                                return 0;
 
458
                                                }
 
459
                                        if (data != sdata)
 
460
                                                {
 
461
                                                OCSP_RESPID_free(id);
 
462
                                                *al = SSL_AD_DECODE_ERROR;
 
463
                                                return 0;
 
464
                                                }
 
465
                                        if (!s->tlsext_ocsp_ids
 
466
                                                && !(s->tlsext_ocsp_ids =
 
467
                                                sk_OCSP_RESPID_new_null()))
 
468
                                                {
 
469
                                                OCSP_RESPID_free(id);
 
470
                                                *al = SSL_AD_INTERNAL_ERROR;
 
471
                                                return 0;
 
472
                                                }
 
473
                                        if (!sk_OCSP_RESPID_push(
 
474
                                                        s->tlsext_ocsp_ids, id))
 
475
                                                {
 
476
                                                OCSP_RESPID_free(id);
 
477
                                                *al = SSL_AD_INTERNAL_ERROR;
 
478
                                                return 0;
 
479
                                                }
 
480
                                        }
 
481
 
 
482
                                /* Read in request_extensions */
 
483
                                n2s(data,dsize);
 
484
                                size -= 2;
 
485
                                if (dsize > size) 
 
486
                                        {
 
487
                                        *al = SSL_AD_DECODE_ERROR;
 
488
                                        return 0;
 
489
                                        }
 
490
                                sdata = data;
 
491
                                if (dsize > 0)
 
492
                                        {
 
493
                                        s->tlsext_ocsp_exts =
 
494
                                                d2i_X509_EXTENSIONS(NULL,
 
495
                                                        &sdata, dsize);
 
496
                                        if (!s->tlsext_ocsp_exts
 
497
                                                || (data + dsize != sdata))
 
498
                                                {
 
499
                                                *al = SSL_AD_DECODE_ERROR;
 
500
                                                return 0;
 
501
                                                }
 
502
                                        }
 
503
                                }
 
504
                                /* We don't know what to do with any other type
 
505
                                * so ignore it.
 
506
                                */
 
507
                                else
 
508
                                        s->tlsext_status_type = -1;
 
509
                        }
352
510
                /* session ticket processed earlier */
353
511
 
354
512
                data+=size;             
403
561
                                }
404
562
                        s->tlsext_ticket_expected = 1;
405
563
                        }
 
564
                else if (type == TLSEXT_TYPE_status_request)
 
565
                        {
 
566
                        /* MUST be empty and only sent if we've requested
 
567
                         * a status request message.
 
568
                         */ 
 
569
                        if ((s->tlsext_status_type == -1) || (size > 0))
 
570
                                {
 
571
                                *al = TLS1_AD_UNSUPPORTED_EXTENSION;
 
572
                                return 0;
 
573
                                }
 
574
                        /* Set flag to expect CertificateStatus message */
 
575
                        s->tlsext_status_expected = 1;
 
576
                        }
406
577
 
407
578
                data+=size;             
408
579
                }
448
619
        else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)             
449
620
                ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
450
621
 
 
622
        /* If status request then ask callback what to do.
 
623
         * Note: this must be called after servername callbacks in case 
 
624
         * the certificate has changed.
 
625
         */
 
626
        if ((s->tlsext_status_type != -1) && s->ctx->tlsext_status_cb)
 
627
                {
 
628
                int r;
 
629
                r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
 
630
                switch (r)
 
631
                        {
 
632
                        /* We don't want to send a status request response */
 
633
                        case SSL_TLSEXT_ERR_NOACK:
 
634
                                s->tlsext_status_expected = 0;
 
635
                                break;
 
636
                        /* status request response should be sent */
 
637
                        case SSL_TLSEXT_ERR_OK:
 
638
                                if (s->tlsext_ocsp_resp)
 
639
                                        s->tlsext_status_expected = 1;
 
640
                                else
 
641
                                        s->tlsext_status_expected = 0;
 
642
                                break;
 
643
                        /* something bad happened */
 
644
                        case SSL_TLSEXT_ERR_ALERT_FATAL:
 
645
                                ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 
646
                                al = SSL_AD_INTERNAL_ERROR;
 
647
                                goto err;
 
648
                        }
 
649
                }
 
650
        else
 
651
                s->tlsext_status_expected = 0;
 
652
        err:
451
653
        switch (ret)
452
654
                {
453
655
                case SSL_TLSEXT_ERR_ALERT_FATAL:
475
677
        else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)             
476
678
                ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
477
679
 
 
680
        /* If we've requested certificate status and we wont get one
 
681
         * tell the callback
 
682
         */
 
683
        if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
 
684
                        && s->ctx->tlsext_status_cb)
 
685
                {
 
686
                int r;
 
687
                /* Set resp to NULL, resplen to -1 so callback knows
 
688
                 * there is no response.
 
689
                 */
 
690
                if (s->tlsext_ocsp_resp)
 
691
                        {
 
692
                        OPENSSL_free(s->tlsext_ocsp_resp);
 
693
                        s->tlsext_ocsp_resp = NULL;
 
694
                        }
 
695
                s->tlsext_ocsp_resplen = -1;
 
696
                r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
 
697
                if (r == 0)
 
698
                        {
 
699
                        al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
 
700
                        ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 
701
                        }
 
702
                if (r < 0)
 
703
                        {
 
704
                        al = SSL_AD_INTERNAL_ERROR;
 
705
                        ret = SSL_TLSEXT_ERR_ALERT_FATAL;
 
706
                        }
 
707
                }
 
708
 
478
709
        switch (ret)
479
710
                {
480
711
                case SSL_TLSEXT_ERR_ALERT_FATAL:
503
734
        /* Point after session ID in client hello */
504
735
        const unsigned char *p = session_id + len;
505
736
        unsigned short i;
 
737
 
 
738
        /* If tickets disabled behave as if no ticket present
 
739
         * to permit stateful resumption.
 
740
         */
 
741
        if (SSL_get_options(s) & SSL_OP_NO_TICKET)
 
742
                return 1;
 
743
 
506
744
        if ((s->version <= SSL3_VERSION) || !limit)
507
745
                return 1;
508
746
        if (p >= limit)
530
768
                        return 1;
531
769
                if (type == TLSEXT_TYPE_session_ticket)
532
770
                        {
533
 
                        /* If tickets disabled indicate cache miss which will
534
 
                         * trigger a full handshake
535
 
                         */
536
 
                        if (SSL_get_options(s) & SSL_OP_NO_TICKET)
537
 
                                return 0;
538
 
                        /* If zero length not client will accept a ticket
 
771
                        /* If zero length note client will accept a ticket
539
772
                         * and indicate cache miss to trigger full handshake
540
773
                         */
541
774
                        if (size == 0)
558
791
        SSL_SESSION *sess;
559
792
        unsigned char *sdec;
560
793
        const unsigned char *p;
561
 
        int slen, mlen;
 
794
        int slen, mlen, renew_ticket = 0;
562
795
        unsigned char tick_hmac[EVP_MAX_MD_SIZE];
563
796
        HMAC_CTX hctx;
564
797
        EVP_CIPHER_CTX ctx;
 
798
        /* Need at least keyname + iv + some encrypted data */
 
799
        if (eticklen < 48)
 
800
                goto tickerr;
 
801
        /* Initialize session ticket encryption and HMAC contexts */
 
802
        HMAC_CTX_init(&hctx);
 
803
        EVP_CIPHER_CTX_init(&ctx);
 
804
        if (s->ctx->tlsext_ticket_key_cb)
 
805
                {
 
806
                unsigned char *nctick = (unsigned char *)etick;
 
807
                int rv = s->ctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
 
808
                                                        &ctx, &hctx, 0);
 
809
                if (rv < 0)
 
810
                        return -1;
 
811
                if (rv == 0)
 
812
                        goto tickerr;
 
813
                if (rv == 2)
 
814
                        renew_ticket = 1;
 
815
                }
 
816
        else
 
817
                {
 
818
                /* Check key name matches */
 
819
                if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16))
 
820
                        goto tickerr;
 
821
                HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
 
822
                                        tlsext_tick_md(), NULL);
 
823
                EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
 
824
                                s->ctx->tlsext_tick_aes_key, etick + 16);
 
825
                }
565
826
        /* Attempt to process session ticket, first conduct sanity and
566
827
         * integrity checks on ticket.
567
828
         */
568
 
        mlen = EVP_MD_size(tlsext_tick_md());
 
829
        mlen = HMAC_size(&hctx);
569
830
        eticklen -= mlen;
570
 
        /* Need at least keyname + iv + some encrypted data */
571
 
        if (eticklen < 48)
572
 
                goto tickerr;
573
 
        /* Check key name matches */
574
 
        if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16))
575
 
                goto tickerr;
576
831
        /* Check HMAC of encrypted ticket */
577
 
        HMAC_CTX_init(&hctx);
578
 
        HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
579
 
                                tlsext_tick_md(), NULL);
580
832
        HMAC_Update(&hctx, etick, eticklen);
581
833
        HMAC_Final(&hctx, tick_hmac, NULL);
582
834
        HMAC_CTX_cleanup(&hctx);
583
835
        if (memcmp(tick_hmac, etick + eticklen, mlen))
584
836
                goto tickerr;
585
 
        /* Set p to start of IV */
586
 
        p = etick + 16;
587
 
        EVP_CIPHER_CTX_init(&ctx);
588
837
        /* Attempt to decrypt session data */
589
 
        EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
590
 
                                        s->ctx->tlsext_tick_aes_key, p);
591
838
        /* Move p after IV to start of encrypted ticket, update length */
592
 
        p += 16;
593
 
        eticklen -= 32;
 
839
        p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
 
840
        eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
594
841
        sdec = OPENSSL_malloc(eticklen);
595
842
        if (!sdec)
596
843
                {
617
864
                        memcpy(sess->session_id, sess_id, sesslen);
618
865
                sess->session_id_length = sesslen;
619
866
                *psess = sess;
620
 
                s->tlsext_ticket_expected = 0;
 
867
                s->tlsext_ticket_expected = renew_ticket;
621
868
                return 1;
622
869
                }
623
870
        /* If session decrypt failure indicate a cache miss and set state to