The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/port/devtls.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0
    3  */
    4 #include        "u.h"
    5 #include        "../port/lib.h"
    6 #include        "mem.h"
    7 #include        "dat.h"
    8 #include        "fns.h"
    9 #include        "../port/error.h"
   10 
   11 #include        <libsec.h>
   12 
   13 typedef struct OneWay   OneWay;
   14 typedef struct Secret           Secret;
   15 typedef struct TlsRec   TlsRec;
   16 typedef struct TlsErrs  TlsErrs;
   17 
   18 enum {
   19         Statlen=        1024,           /* max. length of status or stats message */
   20         /* buffer limits */
   21         MaxRecLen               = 1<<14,        /* max payload length of a record layer message */
   22         MaxCipherRecLen = MaxRecLen + 2048,
   23         RecHdrLen               = 5,
   24         MaxMacLen               = SHA1dlen,
   25 
   26         /* protocol versions we can accept */
   27         TLSVersion              = 0x0301,
   28         SSL3Version             = 0x0300,
   29         ProtocolVersion = 0x0301,       /* maximum version we speak */
   30         MinProtoVersion = 0x0300,       /* limits on version we accept */
   31         MaxProtoVersion = 0x03ff,
   32 
   33         /* connection states */
   34         SHandshake      = 1 << 0,       /* doing handshake */
   35         SOpen           = 1 << 1,       /* application data can be sent */
   36         SRClose         = 1 << 2,       /* remote side has closed down */
   37         SLClose         = 1 << 3,       /* sent a close notify alert */
   38         SAlert          = 1 << 5,       /* sending or sent a fatal alert */
   39         SError          = 1 << 6,       /* some sort of error has occured */
   40         SClosed         = 1 << 7,       /* it is all over */
   41 
   42         /* record types */
   43         RChangeCipherSpec = 20,
   44         RAlert,
   45         RHandshake,
   46         RApplication,
   47 
   48         SSL2ClientHello = 1,
   49         HSSL2ClientHello = 9,  /* local convention;  see tlshand.c */
   50 
   51         /* alerts */
   52         ECloseNotify                    = 0,
   53         EUnexpectedMessage      = 10,
   54         EBadRecordMac           = 20,
   55         EDecryptionFailed               = 21,
   56         ERecordOverflow                 = 22,
   57         EDecompressionFailure   = 30,
   58         EHandshakeFailure               = 40,
   59         ENoCertificate                  = 41,
   60         EBadCertificate                 = 42,
   61         EUnsupportedCertificate         = 43,
   62         ECertificateRevoked             = 44,
   63         ECertificateExpired             = 45,
   64         ECertificateUnknown     = 46,
   65         EIllegalParameter               = 47,
   66         EUnknownCa                      = 48,
   67         EAccessDenied           = 49,
   68         EDecodeError                    = 50,
   69         EDecryptError                   = 51,
   70         EExportRestriction              = 60,
   71         EProtocolVersion                = 70,
   72         EInsufficientSecurity   = 71,
   73         EInternalError                  = 80,
   74         EUserCanceled                   = 90,
   75         ENoRenegotiation                = 100,
   76 
   77         EMAX = 256
   78 };
   79 
   80 struct Secret
   81 {
   82         char            *encalg;        /* name of encryption alg */
   83         char            *hashalg;       /* name of hash alg */
   84         int             (*enc)(Secret*, uchar*, int);
   85         int             (*dec)(Secret*, uchar*, int);
   86         int             (*unpad)(uchar*, int, int);
   87         DigestState     *(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
   88         int             block;          /* encryption block len, 0 if none */
   89         int             maclen;
   90         void            *enckey;
   91         uchar   mackey[MaxMacLen];
   92 };
   93 
   94 struct OneWay
   95 {
   96         QLock           io;             /* locks io access */
   97         QLock           seclock;        /* locks secret paramaters */
   98         ulong           seq;
   99         Secret          *sec;           /* cipher in use */
  100         Secret          *new;           /* cipher waiting for enable */
  101 };
  102 
  103 struct TlsRec
  104 {
  105         Chan    *c;                             /* io channel */
  106         int             ref;                            /* serialized by tdlock for atomic destroy */
  107         int             version;                        /* version of the protocol we are speaking */
  108         char            verset;                 /* version has been set */
  109         char            opened;                 /* opened command every issued? */
  110         char            err[ERRMAX];            /* error message to return to handshake requests */
  111         vlong   handin;                 /* bytes communicated by the record layer */
  112         vlong   handout;
  113         vlong   datain;
  114         vlong   dataout;
  115 
  116         Lock            statelk;
  117         int             state;
  118         int             debug;
  119 
  120         /* record layer mac functions for different protocol versions */
  121         void            (*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*);
  122 
  123         /* input side -- protected by in.io */
  124         OneWay          in;
  125         Block           *processed;     /* next bunch of application data */
  126         Block           *unprocessed;   /* data read from c but not parsed into records */
  127 
  128         /* handshake queue */
  129         Lock            hqlock;                 /* protects hqref, alloc & free of handq, hprocessed */
  130         int             hqref;
  131         Queue           *handq;         /* queue of handshake messages */
  132         Block           *hprocessed;    /* remainder of last block read from handq */
  133         QLock           hqread;         /* protects reads for hprocessed, handq */
  134 
  135         /* output side */
  136         OneWay          out;
  137 
  138         /* protections */
  139         char            *user;
  140         int             perm;
  141 };
  142 
  143 struct TlsErrs{
  144         int     err;
  145         int     sslerr;
  146         int     tlserr;
  147         int     fatal;
  148         char    *msg;
  149 };
  150 
  151 static TlsErrs tlserrs[] = {
  152         {ECloseNotify,                  ECloseNotify,                   ECloseNotify,                   0,      "close notify"},
  153         {EUnexpectedMessage,    EUnexpectedMessage,     EUnexpectedMessage,     1, "unexpected message"},
  154         {EBadRecordMac,         EBadRecordMac,          EBadRecordMac,          1, "bad record mac"},
  155         {EDecryptionFailed,             EIllegalParameter,              EDecryptionFailed,              1, "decryption failed"},
  156         {ERecordOverflow,               EIllegalParameter,              ERecordOverflow,                1, "record too long"},
  157         {EDecompressionFailure, EDecompressionFailure,  EDecompressionFailure,  1, "decompression failed"},
  158         {EHandshakeFailure,             EHandshakeFailure,              EHandshakeFailure,              1, "could not negotiate acceptable security parameters"},
  159         {ENoCertificate,                ENoCertificate,                 ECertificateUnknown,    1, "no appropriate certificate available"},
  160         {EBadCertificate,               EBadCertificate,                EBadCertificate,                1, "corrupted or invalid certificate"},
  161         {EUnsupportedCertificate,       EUnsupportedCertificate,        EUnsupportedCertificate,        1, "unsupported certificate type"},
  162         {ECertificateRevoked,   ECertificateRevoked,            ECertificateRevoked,            1, "revoked certificate"},
  163         {ECertificateExpired,           ECertificateExpired,            ECertificateExpired,            1, "expired certificate"},
  164         {ECertificateUnknown,   ECertificateUnknown,    ECertificateUnknown,    1, "unacceptable certificate"},
  165         {EIllegalParameter,             EIllegalParameter,              EIllegalParameter,              1, "illegal parameter"},
  166         {EUnknownCa,                    EHandshakeFailure,              EUnknownCa,                     1, "unknown certificate authority"},
  167         {EAccessDenied,         EHandshakeFailure,              EAccessDenied,          1, "access denied"},
  168         {EDecodeError,                  EIllegalParameter,              EDecodeError,                   1, "error decoding message"},
  169         {EDecryptError,                 EIllegalParameter,              EDecryptError,                  1, "error decrypting message"},
  170         {EExportRestriction,            EHandshakeFailure,              EExportRestriction,             1, "export restriction violated"},
  171         {EProtocolVersion,              EIllegalParameter,              EProtocolVersion,               1, "protocol version not supported"},
  172         {EInsufficientSecurity, EHandshakeFailure,              EInsufficientSecurity,  1, "stronger security routines required"},
  173         {EInternalError,                        EHandshakeFailure,              EInternalError,                 1, "internal error"},
  174         {EUserCanceled,         ECloseNotify,                   EUserCanceled,                  0, "handshake canceled by user"},
  175         {ENoRenegotiation,              EUnexpectedMessage,     ENoRenegotiation,               0, "no renegotiation"},
  176 };
  177 
  178 enum
  179 {
  180         /* max. open tls connections */
  181         MaxTlsDevs      = 1024
  182 };
  183 
  184 static  Lock    tdlock;
  185 static  int     tdhiwat;
  186 static  int     maxtlsdevs = 128;
  187 static  TlsRec  **tlsdevs;
  188 static  char    **trnames;
  189 static  char    *encalgs;
  190 static  char    *hashalgs;
  191 
  192 enum{
  193         Qtopdir         = 1,    /* top level directory */
  194         Qprotodir,
  195         Qclonus,
  196         Qencalgs,
  197         Qhashalgs,
  198         Qconvdir,               /* directory for a conversation */
  199         Qdata,
  200         Qctl,
  201         Qhand,
  202         Qstatus,
  203         Qstats,
  204 };
  205 
  206 #define TYPE(x)         ((x).path & 0xf)
  207 #define CONV(x)         (((x).path >> 5)&(MaxTlsDevs-1))
  208 #define QID(c, y)       (((c)<<5) | (y))
  209 
  210 static void     checkstate(TlsRec *, int, int);
  211 static void     ensure(TlsRec*, Block**, int);
  212 static void     consume(Block**, uchar*, int);
  213 static Chan*    buftochan(char*);
  214 static void     tlshangup(TlsRec*);
  215 static void     tlsError(TlsRec*, char *);
  216 static void     alertHand(TlsRec*, char *);
  217 static TlsRec   *newtls(Chan *c);
  218 static TlsRec   *mktlsrec(void);
  219 static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
  220 static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
  221 static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
  222 static void     sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
  223 static void     tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
  224 static void     put64(uchar *p, vlong x);
  225 static void     put32(uchar *p, u32int);
  226 static void     put24(uchar *p, int);
  227 static void     put16(uchar *p, int);
  228 static u32int   get32(uchar *p);
  229 static int      get16(uchar *p);
  230 static void     tlsSetState(TlsRec *tr, int new, int old);
  231 static void     rcvAlert(TlsRec *tr, int err);
  232 static void     sendAlert(TlsRec *tr, int err);
  233 static void     rcvError(TlsRec *tr, int err, char *msg, ...);
  234 static int      rc4enc(Secret *sec, uchar *buf, int n);
  235 static int      des3enc(Secret *sec, uchar *buf, int n);
  236 static int      des3dec(Secret *sec, uchar *buf, int n);
  237 static int      noenc(Secret *sec, uchar *buf, int n);
  238 static int      sslunpad(uchar *buf, int n, int block);
  239 static int      tlsunpad(uchar *buf, int n, int block);
  240 static void     freeSec(Secret *sec);
  241 static char     *tlsstate(int s);
  242 static void     pdump(int, void*, char*);
  243 
  244 #pragma varargck        argpos  rcvError        3
  245 
  246 static char *tlsnames[] = {
  247 [Qclonus]               "clone",
  248 [Qencalgs]      "encalgs",
  249 [Qhashalgs]     "hashalgs",
  250 [Qdata]         "data",
  251 [Qctl]          "ctl",
  252 [Qhand]         "hand",
  253 [Qstatus]               "status",
  254 [Qstats]                "stats",
  255 };
  256 
  257 static int convdir[] = { Qctl, Qdata, Qhand, Qstatus, Qstats };
  258 
  259 static int
  260 tlsgen(Chan *c, char*, Dirtab *, int, int s, Dir *dp)
  261 {
  262         Qid q;
  263         TlsRec *tr;
  264         char *name, *nm;
  265         int perm, t;
  266 
  267         q.vers = 0;
  268         q.type = QTFILE;
  269 
  270         t = TYPE(c->qid);
  271         switch(t) {
  272         case Qtopdir:
  273                 if(s == DEVDOTDOT){
  274                         q.path = QID(0, Qtopdir);
  275                         q.type = QTDIR;
  276                         devdir(c, q, "#a", 0, eve, 0555, dp);
  277                         return 1;
  278                 }
  279                 if(s > 0)
  280                         return -1;
  281                 q.path = QID(0, Qprotodir);
  282                 q.type = QTDIR;
  283                 devdir(c, q, "tls", 0, eve, 0555, dp);
  284                 return 1;
  285         case Qprotodir:
  286                 if(s == DEVDOTDOT){
  287                         q.path = QID(0, Qtopdir);
  288                         q.type = QTDIR;
  289                         devdir(c, q, ".", 0, eve, 0555, dp);
  290                         return 1;
  291                 }
  292                 if(s < 3){
  293                         switch(s) {
  294                         default:
  295                                 return -1;
  296                         case 0:
  297                                 q.path = QID(0, Qclonus);
  298                                 break;
  299                         case 1:
  300                                 q.path = QID(0, Qencalgs);
  301                                 break;
  302                         case 2:
  303                                 q.path = QID(0, Qhashalgs);
  304                                 break;
  305                         }
  306                         perm = 0444;
  307                         if(TYPE(q) == Qclonus)
  308                                 perm = 0555;
  309                         devdir(c, q, tlsnames[TYPE(q)], 0, eve, perm, dp);
  310                         return 1;
  311                 }
  312                 s -= 3;
  313                 if(s >= tdhiwat)
  314                         return -1;
  315                 q.path = QID(s, Qconvdir);
  316                 q.type = QTDIR;
  317                 lock(&tdlock);
  318                 tr = tlsdevs[s];
  319                 if(tr != nil)
  320                         nm = tr->user;
  321                 else
  322                         nm = eve;
  323                 if((name = trnames[s]) == nil){
  324                         name = trnames[s] = smalloc(16);
  325                         sprint(name, "%d", s);
  326                 }
  327                 devdir(c, q, name, 0, nm, 0555, dp);
  328                 unlock(&tdlock);
  329                 return 1;
  330         case Qconvdir:
  331                 if(s == DEVDOTDOT){
  332                         q.path = QID(0, Qprotodir);
  333                         q.type = QTDIR;
  334                         devdir(c, q, "tls", 0, eve, 0555, dp);
  335                         return 1;
  336                 }
  337                 if(s < 0 || s >= nelem(convdir))
  338                         return -1;
  339                 lock(&tdlock);
  340                 tr = tlsdevs[CONV(c->qid)];
  341                 if(tr != nil){
  342                         nm = tr->user;
  343                         perm = tr->perm;
  344                 }else{
  345                         perm = 0;
  346                         nm = eve;
  347                 }
  348                 t = convdir[s];
  349                 if(t == Qstatus || t == Qstats)
  350                         perm &= 0444;
  351                 q.path = QID(CONV(c->qid), t);
  352                 devdir(c, q, tlsnames[t], 0, nm, perm, dp);
  353                 unlock(&tdlock);
  354                 return 1;
  355         case Qclonus:
  356         case Qencalgs:
  357         case Qhashalgs:
  358                 perm = 0444;
  359                 if(t == Qclonus)
  360                         perm = 0555;
  361                 devdir(c, c->qid, tlsnames[t], 0, eve, perm, dp);
  362                 return 1;
  363         default:
  364                 lock(&tdlock);
  365                 tr = tlsdevs[CONV(c->qid)];
  366                 if(tr != nil){
  367                         nm = tr->user;
  368                         perm = tr->perm;
  369                 }else{
  370                         perm = 0;
  371                         nm = eve;
  372                 }
  373                 if(t == Qstatus || t == Qstats)
  374                         perm &= 0444;
  375                 devdir(c, c->qid, tlsnames[t], 0, nm, perm, dp);
  376                 unlock(&tdlock);
  377                 return 1;
  378         }
  379 }
  380 
  381 static Chan*
  382 tlsattach(char *spec)
  383 {
  384         Chan *c;
  385 
  386         c = devattach('a', spec);
  387         c->qid.path = QID(0, Qtopdir);
  388         c->qid.type = QTDIR;
  389         c->qid.vers = 0;
  390         return c;
  391 }
  392 
  393 static Walkqid*
  394 tlswalk(Chan *c, Chan *nc, char **name, int nname)
  395 {
  396         return devwalk(c, nc, name, nname, nil, 0, tlsgen);
  397 }
  398 
  399 static int
  400 tlsstat(Chan *c, uchar *db, int n)
  401 {
  402         return devstat(c, db, n, nil, 0, tlsgen);
  403 }
  404 
  405 static Chan*
  406 tlsopen(Chan *c, int omode)
  407 {
  408         TlsRec *tr, **pp;
  409         int t, perm;
  410 
  411         perm = 0;
  412         omode &= 3;
  413         switch(omode) {
  414         case OREAD:
  415                 perm = 4;
  416                 break;
  417         case OWRITE:
  418                 perm = 2;
  419                 break;
  420         case ORDWR:
  421                 perm = 6;
  422                 break;
  423         }
  424 
  425         t = TYPE(c->qid);
  426         switch(t) {
  427         default:
  428                 panic("tlsopen");
  429         case Qtopdir:
  430         case Qprotodir:
  431         case Qconvdir:
  432                 if(omode != OREAD)
  433                         error(Eperm);
  434                 break;
  435         case Qclonus:
  436                 tr = newtls(c);
  437                 if(tr == nil)
  438                         error(Enodev);
  439                 break;
  440         case Qctl:
  441         case Qdata:
  442         case Qhand:
  443         case Qstatus:
  444         case Qstats:
  445                 if((t == Qstatus || t == Qstats) && omode != OREAD)
  446                         error(Eperm);
  447                 if(waserror()) {
  448                         unlock(&tdlock);
  449                         nexterror();
  450                 }
  451                 lock(&tdlock);
  452                 pp = &tlsdevs[CONV(c->qid)];
  453                 tr = *pp;
  454                 if(tr == nil)
  455                         error("must open connection using clone");
  456                 if((perm & (tr->perm>>6)) != perm
  457                 && (strcmp(up->user, tr->user) != 0
  458                     || (perm & tr->perm) != perm))
  459                         error(Eperm);
  460                 if(t == Qhand){
  461                         if(waserror()){
  462                                 unlock(&tr->hqlock);
  463                                 nexterror();
  464                         }
  465                         lock(&tr->hqlock);
  466                         if(tr->handq != nil)
  467                                 error(Einuse);
  468                         tr->handq = qopen(2 * MaxCipherRecLen, 0, nil, nil);
  469                         if(tr->handq == nil)
  470                                 error("cannot allocate handshake queue");
  471                         tr->hqref = 1;
  472                         unlock(&tr->hqlock);
  473                         poperror();
  474                 }
  475                 tr->ref++;
  476                 unlock(&tdlock);
  477                 poperror();
  478                 break;
  479         case Qencalgs:
  480         case Qhashalgs:
  481                 if(omode != OREAD)
  482                         error(Eperm);
  483                 break;
  484         }
  485         c->mode = openmode(omode);
  486         c->flag |= COPEN;
  487         c->offset = 0;
  488         c->iounit = qiomaxatomic;
  489         return c;
  490 }
  491 
  492 static int
  493 tlswstat(Chan *c, uchar *dp, int n)
  494 {
  495         Dir *d;
  496         TlsRec *tr;
  497         int rv;
  498 
  499         d = nil;
  500         if(waserror()){
  501                 free(d);
  502                 unlock(&tdlock);
  503                 nexterror();
  504         }
  505 
  506         lock(&tdlock);
  507         tr = tlsdevs[CONV(c->qid)];
  508         if(tr == nil)
  509                 error(Ebadusefd);
  510         if(strcmp(tr->user, up->user) != 0)
  511                 error(Eperm);
  512 
  513         d = smalloc(n + sizeof *d);
  514         rv = convM2D(dp, n, &d[0], (char*) &d[1]);
  515         if(rv == 0)
  516                 error(Eshortstat);
  517         if(!emptystr(d->uid))
  518                 kstrdup(&tr->user, d->uid);
  519         if(d->mode != ~0UL)
  520                 tr->perm = d->mode;
  521 
  522         free(d);
  523         poperror();
  524         unlock(&tdlock);
  525 
  526         return rv;
  527 }
  528 
  529 static void
  530 dechandq(TlsRec *tr)
  531 {
  532         lock(&tr->hqlock);
  533         if(--tr->hqref == 0){
  534                 if(tr->handq != nil){
  535                         qfree(tr->handq);
  536                         tr->handq = nil;
  537                 }
  538                 if(tr->hprocessed != nil){
  539                         freeb(tr->hprocessed);
  540                         tr->hprocessed = nil;
  541                 }
  542         }
  543         unlock(&tr->hqlock);
  544 }
  545 
  546 static void
  547 tlsclose(Chan *c)
  548 {
  549         TlsRec *tr;
  550         int t;
  551 
  552         t = TYPE(c->qid);
  553         switch(t) {
  554         case Qctl:
  555         case Qdata:
  556         case Qhand:
  557         case Qstatus:
  558         case Qstats:
  559                 if((c->flag & COPEN) == 0)
  560                         break;
  561 
  562                 tr = tlsdevs[CONV(c->qid)];
  563                 if(tr == nil)
  564                         break;
  565 
  566                 if(t == Qhand)
  567                         dechandq(tr);
  568 
  569                 lock(&tdlock);
  570                 if(--tr->ref > 0) {
  571                         unlock(&tdlock);
  572                         return;
  573                 }
  574                 tlsdevs[CONV(c->qid)] = nil;
  575                 unlock(&tdlock);
  576 
  577                 if(tr->c != nil && !waserror()){
  578                         checkstate(tr, 0, SOpen|SHandshake|SRClose);
  579                         sendAlert(tr, ECloseNotify);
  580                         poperror();
  581                 }
  582                 tlshangup(tr);
  583                 if(tr->c != nil)
  584                         cclose(tr->c);
  585                 freeSec(tr->in.sec);
  586                 freeSec(tr->in.new);
  587                 freeSec(tr->out.sec);
  588                 freeSec(tr->out.new);
  589                 free(tr->user);
  590                 free(tr);
  591                 break;
  592         }
  593 }
  594 
  595 /*
  596  *  make sure we have at least 'n' bytes in list 'l'
  597  */
  598 static void
  599 ensure(TlsRec *s, Block **l, int n)
  600 {
  601         int sofar, i;
  602         Block *b, *bl;
  603 
  604         sofar = 0;
  605         for(b = *l; b; b = b->next){
  606                 sofar += BLEN(b);
  607                 if(sofar >= n)
  608                         return;
  609                 l = &b->next;
  610         }
  611 
  612         while(sofar < n){
  613                 bl = devtab[s->c->type]->bread(s->c, MaxCipherRecLen + RecHdrLen, 0);
  614                 if(bl == 0)
  615                         error(Ehungup);
  616                 *l = bl;
  617                 i = 0;
  618                 for(b = bl; b; b = b->next){
  619                         i += BLEN(b);
  620                         l = &b->next;
  621                 }
  622                 if(i == 0)
  623                         error(Ehungup);
  624                 sofar += i;
  625         }
  626 if(s->debug) pprint("ensure read %d\n", sofar);
  627 }
  628 
  629 /*
  630  *  copy 'n' bytes from 'l' into 'p' and free
  631  *  the bytes in 'l'
  632  */
  633 static void
  634 consume(Block **l, uchar *p, int n)
  635 {
  636         Block *b;
  637         int i;
  638 
  639         for(; *l && n > 0; n -= i){
  640                 b = *l;
  641                 i = BLEN(b);
  642                 if(i > n)
  643                         i = n;
  644                 memmove(p, b->rp, i);
  645                 b->rp += i;
  646                 p += i;
  647                 if(BLEN(b) < 0)
  648                         panic("consume");
  649                 if(BLEN(b))
  650                         break;
  651                 *l = b->next;
  652                 freeb(b);
  653         }
  654 }
  655 
  656 /*
  657  *  give back n bytes
  658  */
  659 static void
  660 regurgitate(TlsRec *s, uchar *p, int n)
  661 {
  662         Block *b;
  663 
  664         if(n <= 0)
  665                 return;
  666         b = s->unprocessed;
  667         if(s->unprocessed == nil || b->rp - b->base < n) {
  668                 b = allocb(n);
  669                 memmove(b->wp, p, n);
  670                 b->wp += n;
  671                 b->next = s->unprocessed;
  672                 s->unprocessed = b;
  673         } else {
  674                 b->rp -= n;
  675                 memmove(b->rp, p, n);
  676         }
  677 }
  678 
  679 /*
  680  *  remove at most n bytes from the queue
  681  */
  682 static Block*
  683 qgrab(Block **l, int n)
  684 {
  685         Block *bb, *b;
  686         int i;
  687 
  688         b = *l;
  689         if(BLEN(b) == n){
  690                 *l = b->next;
  691                 b->next = nil;
  692                 return b;
  693         }
  694 
  695         i = 0;
  696         for(bb = b; bb != nil && i < n; bb = bb->next)
  697                 i += BLEN(bb);
  698         if(i > n)
  699                 i = n;
  700 
  701         bb = allocb(i);
  702         consume(l, bb->wp, i);
  703         bb->wp += i;
  704         return bb;
  705 }
  706 
  707 static void
  708 tlsclosed(TlsRec *tr, int new)
  709 {
  710         lock(&tr->statelk);
  711         if(tr->state == SOpen || tr->state == SHandshake)
  712                 tr->state = new;
  713         else if((new | tr->state) == (SRClose|SLClose))
  714                 tr->state = SClosed;
  715         unlock(&tr->statelk);
  716         alertHand(tr, "close notify");
  717 }
  718 
  719 /*
  720  *  read and process one tls record layer message
  721  *  must be called with tr->in.io held
  722  *  We can't let Eintrs lose data, since doing so will get
  723  *  us out of sync with the sender and break the reliablity
  724  *  of the channel.  Eintr only happens during the reads in
  725  *  consume.  Therefore we put back any bytes consumed before
  726  *  the last call to ensure.
  727  */
  728 static void
  729 tlsrecread(TlsRec *tr)
  730 {
  731         OneWay *volatile in;
  732         Block *volatile b;
  733         uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen];
  734         int volatile nconsumed;
  735         int len, type, ver, unpad_len;
  736 
  737         nconsumed = 0;
  738         if(waserror()){
  739                 if(strcmp(up->errstr, Eintr) == 0 && !waserror()){
  740                         regurgitate(tr, header, nconsumed);
  741                         poperror();
  742                 }else
  743                         tlsError(tr, "channel error");
  744                 nexterror();
  745         }
  746         ensure(tr, &tr->unprocessed, RecHdrLen);
  747         consume(&tr->unprocessed, header, RecHdrLen);
  748 if(tr->debug)pprint("consumed %d header\n", RecHdrLen);
  749         nconsumed = RecHdrLen;
  750 
  751         if((tr->handin == 0) && (header[0] & 0x80)){
  752                 /* Cope with an SSL3 ClientHello expressed in SSL2 record format.
  753                         This is sent by some clients that we must interoperate
  754                         with, such as Java's JSSE and Microsoft's Internet Explorer. */
  755                 len = (get16(header) & ~0x8000) - 3;
  756                 type = header[2];
  757                 ver = get16(header + 3);
  758                 if(type != SSL2ClientHello || len < 22)
  759                         rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
  760         }else{  /* normal SSL3 record format */
  761                 type = header[0];
  762                 ver = get16(header+1);
  763                 len = get16(header+3);
  764         }
  765         if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
  766                 rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
  767                         tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
  768         if(len > MaxCipherRecLen || len < 0)
  769                 rcvError(tr, ERecordOverflow, "record message too long %d", len);
  770         ensure(tr, &tr->unprocessed, len);
  771         nconsumed = 0;
  772         poperror();
  773 
  774         /*
  775          * If an Eintr happens after this, we'll get out of sync.
  776          * Make sure nothing we call can sleep.
  777          * Errors are ok, as they kill the connection.
  778          * Luckily, allocb won't sleep, it'll just error out.
  779          */
  780         b = nil;
  781         if(waserror()){
  782                 if(b != nil)
  783                         freeb(b);
  784                 tlsError(tr, "channel error");
  785                 nexterror();
  786         }
  787         b = qgrab(&tr->unprocessed, len);
  788 if(tr->debug) pprint("consumed unprocessed %d\n", len);
  789 
  790         in = &tr->in;
  791         if(waserror()){
  792                 qunlock(&in->seclock);
  793                 nexterror();
  794         }
  795         qlock(&in->seclock);
  796         p = b->rp;
  797         if(in->sec != nil) {
  798                 /* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
  799                         should look alike, including timing of the response. */
  800                 unpad_len = (*in->sec->dec)(in->sec, p, len);
  801                 if(unpad_len >= in->sec->maclen)
  802                         len = unpad_len - in->sec->maclen;
  803 if(tr->debug) pprint("decrypted %d\n", unpad_len);
  804 if(tr->debug) pdump(unpad_len, p, "decrypted:");
  805 
  806                 /* update length */
  807                 put16(header+3, len);
  808                 put64(seq, in->seq);
  809                 in->seq++;
  810                 (*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
  811                 if(unpad_len < in->sec->maclen)
  812                         rcvError(tr, EBadRecordMac, "short record mac");
  813                 if(memcmp(hmac, p+len, in->sec->maclen) != 0)
  814                         rcvError(tr, EBadRecordMac, "record mac mismatch");
  815                 b->wp = b->rp + len;
  816         }
  817         qunlock(&in->seclock);
  818         poperror();
  819         if(len < 0)
  820                 rcvError(tr, EDecodeError, "runt record message");
  821 
  822         switch(type) {
  823         default:
  824                 rcvError(tr, EIllegalParameter, "invalid record message %#x", type);
  825                 break;
  826         case RChangeCipherSpec:
  827                 if(len != 1 || p[0] != 1)
  828                         rcvError(tr, EDecodeError, "invalid change cipher spec");
  829                 qlock(&in->seclock);
  830                 if(in->new == nil){
  831                         qunlock(&in->seclock);
  832                         rcvError(tr, EUnexpectedMessage, "unexpected change cipher spec");
  833                 }
  834                 freeSec(in->sec);
  835                 in->sec = in->new;
  836                 in->new = nil;
  837                 in->seq = 0;
  838                 qunlock(&in->seclock);
  839                 break;
  840         case RAlert:
  841                 if(len != 2)
  842                         rcvError(tr, EDecodeError, "invalid alert");
  843                 if(p[0] == 2)
  844                         rcvAlert(tr, p[1]);
  845                 if(p[0] != 1)
  846                         rcvError(tr, EIllegalParameter, "invalid alert fatal code");
  847 
  848                 /*
  849                  * propate non-fatal alerts to handshaker
  850                  */
  851                 if(p[1] == ECloseNotify) {
  852                         tlsclosed(tr, SRClose);
  853                         if(tr->opened)
  854                                 error("tls hungup");
  855                         error("close notify");
  856                 }
  857                 if(p[1] == ENoRenegotiation)
  858                         alertHand(tr, "no renegotiation");
  859                 else if(p[1] == EUserCanceled)
  860                         alertHand(tr, "handshake canceled by user");
  861                 else
  862                         rcvError(tr, EIllegalParameter, "invalid alert code");
  863                 break;
  864         case RHandshake:
  865                 /*
  866                  * don't worry about dropping the block
  867                  * qbwrite always queues even if flow controlled and interrupted.
  868                  *
  869                  * if there isn't any handshaker, ignore the request,
  870                  * but notify the other side we are doing so.
  871                  */
  872                 lock(&tr->hqlock);
  873                 if(tr->handq != nil){
  874                         tr->hqref++;
  875                         unlock(&tr->hqlock);
  876                         if(waserror()){
  877                                 dechandq(tr);
  878                                 nexterror();
  879                         }
  880                         b = padblock(b, 1);
  881                         *b->rp = RHandshake;
  882                         qbwrite(tr->handq, b);
  883                         b = nil;
  884                         poperror();
  885                         dechandq(tr);
  886                 }else{
  887                         unlock(&tr->hqlock);
  888                         if(tr->verset && tr->version != SSL3Version && !waserror()){
  889                                 sendAlert(tr, ENoRenegotiation);
  890                                 poperror();
  891                         }
  892                 }
  893                 break;
  894         case SSL2ClientHello:
  895                 lock(&tr->hqlock);
  896                 if(tr->handq != nil){
  897                         tr->hqref++;
  898                         unlock(&tr->hqlock);
  899                         if(waserror()){
  900                                 dechandq(tr);
  901                                 nexterror();
  902                         }
  903                         /* Pass the SSL2 format data, so that the handshake code can compute
  904                                 the correct checksums.  HSSL2ClientHello = HandshakeType 9 is
  905                                 unused in RFC2246. */
  906                         b = padblock(b, 8);
  907                         b->rp[0] = RHandshake;
  908                         b->rp[1] = HSSL2ClientHello;
  909                         put24(&b->rp[2], len+3);
  910                         b->rp[5] = SSL2ClientHello;
  911                         put16(&b->rp[6], ver);
  912                         qbwrite(tr->handq, b);
  913                         b = nil;
  914                         poperror();
  915                         dechandq(tr);
  916                 }else{
  917                         unlock(&tr->hqlock);
  918                         if(tr->verset && tr->version != SSL3Version && !waserror()){
  919                                 sendAlert(tr, ENoRenegotiation);
  920                                 poperror();
  921                         }
  922                 }
  923                 break;
  924         case RApplication:
  925                 if(!tr->opened)
  926                         rcvError(tr, EUnexpectedMessage, "application message received before handshake completed");
  927                 if(BLEN(b) > 0){
  928                         tr->processed = b;
  929                         b = nil;
  930                 }
  931                 break;
  932         }
  933         if(b != nil)
  934                 freeb(b);
  935         poperror();
  936 }
  937 
  938 /*
  939  * got a fatal alert message
  940  */
  941 static void
  942 rcvAlert(TlsRec *tr, int err)
  943 {
  944         char *s;
  945         int i;
  946 
  947         s = "unknown error";
  948         for(i=0; i < nelem(tlserrs); i++){
  949                 if(tlserrs[i].err == err){
  950                         s = tlserrs[i].msg;
  951                         break;
  952                 }
  953         }
  954 if(tr->debug) pprint("rcvAlert: %s\n", s);
  955 
  956         tlsError(tr, s);
  957         if(!tr->opened)
  958                 error(s);
  959         error("tls error");
  960 }
  961 
  962 /*
  963  * found an error while decoding the input stream
  964  */
  965 static void
  966 rcvError(TlsRec *tr, int err, char *fmt, ...)
  967 {
  968         char msg[ERRMAX];
  969         va_list arg;
  970 
  971         va_start(arg, fmt);
  972         vseprint(msg, msg+sizeof(msg), fmt, arg);
  973         va_end(arg);
  974 if(tr->debug) pprint("rcvError: %s\n", msg);
  975 
  976         sendAlert(tr, err);
  977 
  978         if(!tr->opened)
  979                 error(msg);
  980         error("tls error");
  981 }
  982 
  983 /*
  984  * make sure the next hand operation returns with a 'msg' error
  985  */
  986 static void
  987 alertHand(TlsRec *tr, char *msg)
  988 {
  989         Block *b;
  990         int n;
  991 
  992         lock(&tr->hqlock);
  993         if(tr->handq == nil){
  994                 unlock(&tr->hqlock);
  995                 return;
  996         }
  997         tr->hqref++;
  998         unlock(&tr->hqlock);
  999 
 1000         n = strlen(msg);
 1001         if(waserror()){
 1002                 dechandq(tr);
 1003                 nexterror();
 1004         }
 1005         b = allocb(n + 2);
 1006         *b->wp++ = RAlert;
 1007         memmove(b->wp, msg, n + 1);
 1008         b->wp += n + 1;
 1009 
 1010         qbwrite(tr->handq, b);
 1011 
 1012         poperror();
 1013         dechandq(tr);
 1014 }
 1015 
 1016 static void
 1017 checkstate(TlsRec *tr, int ishand, int ok)
 1018 {
 1019         int state;
 1020 
 1021         lock(&tr->statelk);
 1022         state = tr->state;
 1023         unlock(&tr->statelk);
 1024         if(state & ok)
 1025                 return;
 1026         switch(state){
 1027         case SHandshake:
 1028         case SOpen:
 1029                 break;
 1030         case SError:
 1031         case SAlert:
 1032                 if(ishand)
 1033                         error(tr->err);
 1034                 error("tls error");
 1035         case SRClose:
 1036         case SLClose:
 1037         case SClosed:
 1038                 error("tls hungup");
 1039         }
 1040         error("tls improperly configured");
 1041 }
 1042 
 1043 static Block*
 1044 tlsbread(Chan *c, long n, ulong offset)
 1045 {
 1046         int ty;
 1047         Block *b;
 1048         TlsRec *volatile tr;
 1049 
 1050         ty = TYPE(c->qid);
 1051         switch(ty) {
 1052         default:
 1053                 return devbread(c, n, offset);
 1054         case Qhand:
 1055         case Qdata:
 1056                 break;
 1057         }
 1058 
 1059         tr = tlsdevs[CONV(c->qid)];
 1060         if(tr == nil)
 1061                 panic("tlsbread");
 1062 
 1063         if(waserror()){
 1064                 qunlock(&tr->in.io);
 1065                 nexterror();
 1066         }
 1067         qlock(&tr->in.io);
 1068         if(ty == Qdata){
 1069                 checkstate(tr, 0, SOpen);
 1070                 while(tr->processed == nil)
 1071                         tlsrecread(tr);
 1072 
 1073                 /* return at most what was asked for */
 1074                 b = qgrab(&tr->processed, n);
 1075 if(tr->debug) pprint("consumed processed %d\n", BLEN(b));
 1076 if(tr->debug) pdump(BLEN(b), b->rp, "consumed:");
 1077                 qunlock(&tr->in.io);
 1078                 poperror();
 1079                 tr->datain += BLEN(b);
 1080         }else{
 1081                 checkstate(tr, 1, SOpen|SHandshake|SLClose);
 1082 
 1083                 /*
 1084                  * it's ok to look at state without the lock
 1085                  * since it only protects reading records,
 1086                  * and we have that tr->in.io held.
 1087                  */
 1088                 while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq))
 1089                         tlsrecread(tr);
 1090 
 1091                 qunlock(&tr->in.io);
 1092                 poperror();
 1093 
 1094                 if(waserror()){
 1095                         qunlock(&tr->hqread);
 1096                         nexterror();
 1097                 }
 1098                 qlock(&tr->hqread);
 1099                 if(tr->hprocessed == nil){
 1100                         b = qbread(tr->handq, MaxRecLen + 1);
 1101                         if(*b->rp++ == RAlert){
 1102                                 kstrcpy(up->errstr, (char*)b->rp, ERRMAX);
 1103                                 freeb(b);
 1104                                 nexterror();
 1105                         }
 1106                         tr->hprocessed = b;
 1107                 }
 1108                 b = qgrab(&tr->hprocessed, n);
 1109                 poperror();
 1110                 qunlock(&tr->hqread);
 1111                 tr->handin += BLEN(b);
 1112         }
 1113 
 1114         return b;
 1115 }
 1116 
 1117 static long
 1118 tlsread(Chan *c, void *a, long n, vlong off)
 1119 {
 1120         Block *volatile b;
 1121         Block *nb;
 1122         uchar *va;
 1123         int i, ty;
 1124         char *buf, *s, *e;
 1125         ulong offset = off;
 1126         TlsRec * tr;
 1127 
 1128         if(c->qid.type & QTDIR)
 1129                 return devdirread(c, a, n, 0, 0, tlsgen);
 1130 
 1131         tr = tlsdevs[CONV(c->qid)];
 1132         ty = TYPE(c->qid);
 1133         switch(ty) {
 1134         default:
 1135                 error(Ebadusefd);
 1136         case Qstatus:
 1137                 buf = smalloc(Statlen);
 1138                 qlock(&tr->in.seclock);
 1139                 qlock(&tr->out.seclock);
 1140                 s = buf;
 1141                 e = buf + Statlen;
 1142                 s = seprint(s, e, "State: %s\n", tlsstate(tr->state));
 1143                 s = seprint(s, e, "Version: %#x\n", tr->version);
 1144                 if(tr->in.sec != nil)
 1145                         s = seprint(s, e, "EncIn: %s\nHashIn: %s\n", tr->in.sec->encalg, tr->in.sec->hashalg);
 1146                 if(tr->in.new != nil)
 1147                         s = seprint(s, e, "NewEncIn: %s\nNewHashIn: %s\n", tr->in.new->encalg, tr->in.new->hashalg);
 1148                 if(tr->out.sec != nil)
 1149                         s = seprint(s, e, "EncOut: %s\nHashOut: %s\n", tr->out.sec->encalg, tr->out.sec->hashalg);
 1150                 if(tr->out.new != nil)
 1151                         seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg);
 1152                 qunlock(&tr->in.seclock);
 1153                 qunlock(&tr->out.seclock);
 1154                 n = readstr(offset, a, n, buf);
 1155                 free(buf);
 1156                 return n;
 1157         case Qstats:
 1158                 buf = smalloc(Statlen);
 1159                 s = buf;
 1160                 e = buf + Statlen;
 1161                 s = seprint(s, e, "DataIn: %lld\n", tr->datain);
 1162                 s = seprint(s, e, "DataOut: %lld\n", tr->dataout);
 1163                 s = seprint(s, e, "HandIn: %lld\n", tr->handin);
 1164                 seprint(s, e, "HandOut: %lld\n", tr->handout);
 1165                 n = readstr(offset, a, n, buf);
 1166                 free(buf);
 1167                 return n;
 1168         case Qctl:
 1169                 buf = smalloc(Statlen);
 1170                 snprint(buf, Statlen, "%llud", CONV(c->qid));
 1171                 n = readstr(offset, a, n, buf);
 1172                 free(buf);
 1173                 return n;
 1174         case Qdata:
 1175         case Qhand:
 1176                 b = tlsbread(c, n, offset);
 1177                 break;
 1178         case Qencalgs:
 1179                 return readstr(offset, a, n, encalgs);
 1180         case Qhashalgs:
 1181                 return readstr(offset, a, n, hashalgs);
 1182         }
 1183 
 1184         if(waserror()){
 1185                 freeblist(b);
 1186                 nexterror();
 1187         }
 1188 
 1189         n = 0;
 1190         va = a;
 1191         for(nb = b; nb; nb = nb->next){
 1192                 i = BLEN(nb);
 1193                 memmove(va+n, nb->rp, i);
 1194                 n += i;
 1195         }
 1196 
 1197         freeblist(b);
 1198         poperror();
 1199 
 1200         return n;
 1201 }
 1202 
 1203 /*
 1204  *  write a block in tls records
 1205  */
 1206 static void
 1207 tlsrecwrite(TlsRec *tr, int type, Block *b)
 1208 {
 1209         Block *volatile bb;
 1210         Block *nb;
 1211         uchar *p, seq[8];
 1212         OneWay *volatile out;
 1213         int n, maclen, pad, ok;
 1214 
 1215         out = &tr->out;
 1216         bb = b;
 1217         if(waserror()){
 1218                 qunlock(&out->io);
 1219                 if(bb != nil)
 1220                         freeb(bb);
 1221                 nexterror();
 1222         }
 1223         qlock(&out->io);
 1224 if(tr->debug)pprint("send %d\n", BLEN(b));
 1225 if(tr->debug)pdump(BLEN(b), b->rp, "sent:");
 1226 
 1227 
 1228         ok = SHandshake|SOpen|SRClose;
 1229         if(type == RAlert)
 1230                 ok |= SAlert;
 1231         while(bb != nil){
 1232                 checkstate(tr, type != RApplication, ok);
 1233 
 1234                 /*
 1235                  * get at most one maximal record's input,
 1236                  * with padding on the front for header and
 1237                  * back for mac and maximal block padding.
 1238                  */
 1239                 if(waserror()){
 1240                         qunlock(&out->seclock);
 1241                         nexterror();
 1242                 }
 1243                 qlock(&out->seclock);
 1244                 maclen = 0;
 1245                 pad = 0;
 1246                 if(out->sec != nil){
 1247                         maclen = out->sec->maclen;
 1248                         pad = maclen + out->sec->block;
 1249                 }
 1250                 n = BLEN(bb);
 1251                 if(n > MaxRecLen){
 1252                         n = MaxRecLen;
 1253                         nb = allocb(n + pad + RecHdrLen);
 1254                         memmove(nb->wp + RecHdrLen, bb->rp, n);
 1255                         bb->rp += n;
 1256                 }else{
 1257                         /*
 1258                          * carefully reuse bb so it will get freed if we're out of memory
 1259                          */
 1260                         bb = padblock(bb, RecHdrLen);
 1261                         if(pad)
 1262                                 nb = padblock(bb, -pad);
 1263                         else
 1264                                 nb = bb;
 1265                         bb = nil;
 1266                 }
 1267 
 1268                 p = nb->rp;
 1269                 p[0] = type;
 1270                 put16(p+1, tr->version);
 1271                 put16(p+3, n);
 1272 
 1273                 if(out->sec != nil){
 1274                         put64(seq, out->seq);
 1275                         out->seq++;
 1276                         (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n);
 1277                         n += maclen;
 1278 
 1279                         /* encrypt */
 1280                         n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
 1281                         nb->wp = p + RecHdrLen + n;
 1282 
 1283                         /* update length */
 1284                         put16(p+3, n);
 1285                 }
 1286                 if(type == RChangeCipherSpec){
 1287                         if(out->new == nil)
 1288                                 error("change cipher without a new cipher");
 1289                         freeSec(out->sec);
 1290                         out->sec = out->new;
 1291                         out->new = nil;
 1292                         out->seq = 0;
 1293                 }
 1294                 qunlock(&out->seclock);
 1295                 poperror();
 1296 
 1297                 /*
 1298                  * if bwrite error's, we assume the block is queued.
 1299                  * if not, we're out of sync with the receiver and will not recover.
 1300                  */
 1301                 if(waserror()){
 1302                         if(strcmp(up->errstr, "interrupted") != 0)
 1303                                 tlsError(tr, "channel error");
 1304                         nexterror();
 1305                 }
 1306                 devtab[tr->c->type]->bwrite(tr->c, nb, 0);
 1307                 poperror();
 1308         }
 1309         qunlock(&out->io);
 1310         poperror();
 1311 }
 1312 
 1313 static long
 1314 tlsbwrite(Chan *c, Block *b, ulong offset)
 1315 {
 1316         int ty;
 1317         ulong n;
 1318         TlsRec *tr;
 1319 
 1320         n = BLEN(b);
 1321 
 1322         tr = tlsdevs[CONV(c->qid)];
 1323         if(tr == nil)
 1324                 panic("tlsbread");
 1325 
 1326         ty = TYPE(c->qid);
 1327         switch(ty) {
 1328         default:
 1329                 return devbwrite(c, b, offset);
 1330         case Qhand:
 1331                 tlsrecwrite(tr, RHandshake, b);
 1332                 tr->handout += n;
 1333                 break;
 1334         case Qdata:
 1335                 checkstate(tr, 0, SOpen);
 1336                 tlsrecwrite(tr, RApplication, b);
 1337                 tr->dataout += n;
 1338                 break;
 1339         }
 1340 
 1341         return n;
 1342 }
 1343 
 1344 typedef struct Hashalg Hashalg;
 1345 struct Hashalg
 1346 {
 1347         char    *name;
 1348         int     maclen;
 1349         void    (*initkey)(Hashalg *, int, Secret *, uchar*);
 1350 };
 1351 
 1352 static void
 1353 initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
 1354 {
 1355         s->maclen = ha->maclen;
 1356         if(version == SSL3Version)
 1357                 s->mac = sslmac_md5;
 1358         else
 1359                 s->mac = hmac_md5;
 1360         memmove(s->mackey, p, ha->maclen);
 1361 }
 1362 
 1363 static void
 1364 initclearmac(Hashalg *, int, Secret *s, uchar *)
 1365 {
 1366         s->maclen = 0;
 1367         s->mac = nomac;
 1368 }
 1369 
 1370 static void
 1371 initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
 1372 {
 1373         s->maclen = ha->maclen;
 1374         if(version == SSL3Version)
 1375                 s->mac = sslmac_sha1;
 1376         else
 1377                 s->mac = hmac_sha1;
 1378         memmove(s->mackey, p, ha->maclen);
 1379 }
 1380 
 1381 static Hashalg hashtab[] =
 1382 {
 1383         { "clear", 0, initclearmac, },
 1384         { "md5", MD5dlen, initmd5key, },
 1385         { "sha1", SHA1dlen, initsha1key, },
 1386         { 0 }
 1387 };
 1388 
 1389 static Hashalg*
 1390 parsehashalg(char *p)
 1391 {
 1392         Hashalg *ha;
 1393 
 1394         for(ha = hashtab; ha->name; ha++)
 1395                 if(strcmp(p, ha->name) == 0)
 1396                         return ha;
 1397         error("unsupported hash algorithm");
 1398         return nil;
 1399 }
 1400 
 1401 typedef struct Encalg Encalg;
 1402 struct Encalg
 1403 {
 1404         char    *name;
 1405         int     keylen;
 1406         int     ivlen;
 1407         void    (*initkey)(Encalg *ea, Secret *, uchar*, uchar*);
 1408 };
 1409 
 1410 static void
 1411 initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *)
 1412 {
 1413         s->enckey = smalloc(sizeof(RC4state));
 1414         s->enc = rc4enc;
 1415         s->dec = rc4enc;
 1416         s->block = 0;
 1417         setupRC4state(s->enckey, p, ea->keylen);
 1418 }
 1419 
 1420 static void
 1421 initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv)
 1422 {
 1423         s->enckey = smalloc(sizeof(DES3state));
 1424         s->enc = des3enc;
 1425         s->dec = des3dec;
 1426         s->block = 8;
 1427         setupDES3state(s->enckey, (uchar(*)[8])p, iv);
 1428 }
 1429 
 1430 static void
 1431 initclearenc(Encalg *, Secret *s, uchar *, uchar *)
 1432 {
 1433         s->enc = noenc;
 1434         s->dec = noenc;
 1435         s->block = 0;
 1436 }
 1437 
 1438 static Encalg encrypttab[] =
 1439 {
 1440         { "clear", 0, 0, initclearenc },
 1441         { "rc4_128", 128/8, 0, initRC4key },
 1442         { "3des_ede_cbc", 3 * 8, 8, initDES3key },
 1443         { 0 }
 1444 };
 1445 
 1446 static Encalg*
 1447 parseencalg(char *p)
 1448 {
 1449         Encalg *ea;
 1450 
 1451         for(ea = encrypttab; ea->name; ea++)
 1452                 if(strcmp(p, ea->name) == 0)
 1453                         return ea;
 1454         error("unsupported encryption algorithm");
 1455         return nil;
 1456 }
 1457 
 1458 static long
 1459 tlswrite(Chan *c, void *a, long n, vlong off)
 1460 {
 1461         Encalg *ea;
 1462         Hashalg *ha;
 1463         TlsRec *volatile tr;
 1464         Secret *volatile tos, *volatile toc;
 1465         Block *volatile b;
 1466         Cmdbuf *volatile cb;
 1467         int m, ty;
 1468         char *p, *e;
 1469         uchar *volatile x;
 1470         ulong offset = off;
 1471 
 1472         tr = tlsdevs[CONV(c->qid)];
 1473         if(tr == nil)
 1474                 panic("tlswrite");
 1475 
 1476         ty = TYPE(c->qid);
 1477         switch(ty){
 1478         case Qdata:
 1479         case Qhand:
 1480                 p = a;
 1481                 e = p + n;
 1482                 do{
 1483                         m = e - p;
 1484                         if(m > MaxRecLen)
 1485                                 m = MaxRecLen;
 1486 
 1487                         b = allocb(m);
 1488                         if(waserror()){
 1489                                 freeb(b);
 1490                                 nexterror();
 1491                         }
 1492                         memmove(b->wp, p, m);
 1493                         poperror();
 1494                         b->wp += m;
 1495 
 1496                         tlsbwrite(c, b, offset);
 1497 
 1498                         p += m;
 1499                 }while(p < e);
 1500                 return n;
 1501         case Qctl:
 1502                 break;
 1503         default:
 1504                 error(Ebadusefd);
 1505                 return -1;
 1506         }
 1507 
 1508         cb = parsecmd(a, n);
 1509         if(waserror()){
 1510                 free(cb);
 1511                 nexterror();
 1512         }
 1513         if(cb->nf < 1)
 1514                 error("short control request");
 1515 
 1516         /* mutex with operations using what we're about to change */
 1517         if(waserror()){
 1518                 qunlock(&tr->in.seclock);
 1519                 qunlock(&tr->out.seclock);
 1520                 nexterror();
 1521         }
 1522         qlock(&tr->in.seclock);
 1523         qlock(&tr->out.seclock);
 1524 
 1525         if(strcmp(cb->f[0], "fd") == 0){
 1526                 if(cb->nf != 3)
 1527                         error("usage: fd open-fd version");
 1528                 if(tr->c != nil)
 1529                         error(Einuse);
 1530                 m = strtol(cb->f[2], nil, 0);
 1531                 if(m < MinProtoVersion || m > MaxProtoVersion)
 1532                         error("unsupported version");
 1533                 tr->c = buftochan(cb->f[1]);
 1534                 tr->version = m;
 1535                 tlsSetState(tr, SHandshake, SClosed);
 1536         }else if(strcmp(cb->f[0], "version") == 0){
 1537                 if(cb->nf != 2)
 1538                         error("usage: version vers");
 1539                 if(tr->c == nil)
 1540                         error("must set fd before version");
 1541                 if(tr->verset)
 1542                         error("version already set");
 1543                 m = strtol(cb->f[1], nil, 0);
 1544                 if(m == SSL3Version)
 1545                         tr->packMac = sslPackMac;
 1546                 else if(m == TLSVersion)
 1547                         tr->packMac = tlsPackMac;
 1548                 else
 1549                         error("unsupported version");
 1550                 tr->verset = 1;
 1551                 tr->version = m;
 1552         }else if(strcmp(cb->f[0], "secret") == 0){
 1553                 if(cb->nf != 5)
 1554                         error("usage: secret hashalg encalg isclient secretdata");
 1555                 if(tr->c == nil || !tr->verset)
 1556                         error("must set fd and version before secrets");
 1557 
 1558                 if(tr->in.new != nil){
 1559                         freeSec(tr->in.new);
 1560                         tr->in.new = nil;
 1561                 }
 1562                 if(tr->out.new != nil){
 1563                         freeSec(tr->out.new);
 1564                         tr->out.new = nil;
 1565                 }
 1566 
 1567                 ha = parsehashalg(cb->f[1]);
 1568                 ea = parseencalg(cb->f[2]);
 1569 
 1570                 p = cb->f[4];
 1571                 m = (strlen(p)*3)/2;
 1572                 x = smalloc(m);
 1573                 tos = nil;
 1574                 toc = nil;
 1575                 if(waserror()){
 1576                         freeSec(tos);
 1577                         freeSec(toc);
 1578                         free(x);
 1579                         nexterror();
 1580                 }
 1581                 m = dec64(x, m, p, strlen(p));
 1582                 if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen)
 1583                         error("not enough secret data provided");
 1584 
 1585                 tos = smalloc(sizeof(Secret));
 1586                 toc = smalloc(sizeof(Secret));
 1587                 if(!ha->initkey || !ea->initkey)
 1588                         error("misimplemented secret algorithm");
 1589                 (*ha->initkey)(ha, tr->version, tos, &x[0]);
 1590                 (*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
 1591                 (*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
 1592                 (*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
 1593 
 1594                 if(!tos->mac || !tos->enc || !tos->dec
 1595                 || !toc->mac || !toc->enc || !toc->dec)
 1596                         error("missing algorithm implementations");
 1597                 if(strtol(cb->f[3], nil, 0) == 0){
 1598                         tr->in.new = tos;
 1599                         tr->out.new = toc;
 1600                 }else{
 1601                         tr->in.new = toc;
 1602                         tr->out.new = tos;
 1603                 }
 1604                 if(tr->version == SSL3Version){
 1605                         toc->unpad = sslunpad;
 1606                         tos->unpad = sslunpad;
 1607                 }else{
 1608                         toc->unpad = tlsunpad;
 1609                         tos->unpad = tlsunpad;
 1610                 }
 1611                 toc->encalg = ea->name;
 1612                 toc->hashalg = ha->name;
 1613                 tos->encalg = ea->name;
 1614                 tos->hashalg = ha->name;
 1615 
 1616                 free(x);
 1617                 poperror();
 1618         }else if(strcmp(cb->f[0], "changecipher") == 0){
 1619                 if(cb->nf != 1)
 1620                         error("usage: changecipher");
 1621                 if(tr->out.new == nil)
 1622                         error("cannot change cipher spec without setting secret");
 1623 
 1624                 qunlock(&tr->in.seclock);
 1625                 qunlock(&tr->out.seclock);
 1626                 poperror();
 1627                 free(cb);
 1628                 poperror();
 1629 
 1630                 /*
 1631                  * the real work is done as the message is written
 1632                  * so the stream is encrypted in sync.
 1633                  */
 1634                 b = allocb(1);
 1635                 *b->wp++ = 1;
 1636                 tlsrecwrite(tr, RChangeCipherSpec, b);
 1637                 return n;
 1638         }else if(strcmp(cb->f[0], "opened") == 0){
 1639                 if(cb->nf != 1)
 1640                         error("usage: opened");
 1641                 if(tr->in.sec == nil || tr->out.sec == nil)
 1642                         error("cipher must be configured before enabling data messages");
 1643                 lock(&tr->statelk);
 1644                 if(tr->state != SHandshake && tr->state != SOpen){
 1645                         unlock(&tr->statelk);
 1646                         error("cannot enable data messages");
 1647                 }
 1648                 tr->state = SOpen;
 1649                 unlock(&tr->statelk);
 1650                 tr->opened = 1;
 1651         }else if(strcmp(cb->f[0], "alert") == 0){
 1652                 if(cb->nf != 2)
 1653                         error("usage: alert n");
 1654                 if(tr->c == nil)
 1655                         error("must set fd before sending alerts");
 1656                 m = strtol(cb->f[1], nil, 0);
 1657 
 1658                 qunlock(&tr->in.seclock);
 1659                 qunlock(&tr->out.seclock);
 1660                 poperror();
 1661                 free(cb);
 1662                 poperror();
 1663 
 1664                 sendAlert(tr, m);
 1665 
 1666                 if(m == ECloseNotify)
 1667                         tlsclosed(tr, SLClose);
 1668 
 1669                 return n;
 1670         } else if(strcmp(cb->f[0], "debug") == 0){
 1671                 if(cb->nf == 2){
 1672                         if(strcmp(cb->f[1], "on") == 0)
 1673                                 tr->debug = 1;
 1674                         else
 1675                                 tr->debug = 0;
 1676                 } else
 1677                         tr->debug = 1;
 1678         } else
 1679                 error(Ebadarg);
 1680 
 1681         qunlock(&tr->in.seclock);
 1682         qunlock(&tr->out.seclock);
 1683         poperror();
 1684         free(cb);
 1685         poperror();
 1686 
 1687         return n;
 1688 }
 1689 
 1690 static void
 1691 tlsinit(void)
 1692 {
 1693         struct Encalg *e;
 1694         struct Hashalg *h;
 1695         int n;
 1696         char *cp;
 1697         static int already;
 1698 
 1699         if(!already){
 1700                 fmtinstall('H', encodefmt);
 1701                 already = 1;
 1702         }
 1703 
 1704         tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs);
 1705         trnames = smalloc((sizeof *trnames) * maxtlsdevs);
 1706 
 1707         n = 1;
 1708         for(e = encrypttab; e->name != nil; e++)
 1709                 n += strlen(e->name) + 1;
 1710         cp = encalgs = smalloc(n);
 1711         for(e = encrypttab;;){
 1712                 strcpy(cp, e->name);
 1713                 cp += strlen(e->name);
 1714                 e++;
 1715                 if(e->name == nil)
 1716                         break;
 1717                 *cp++ = ' ';
 1718         }
 1719         *cp = 0;
 1720 
 1721         n = 1;
 1722         for(h = hashtab; h->name != nil; h++)
 1723                 n += strlen(h->name) + 1;
 1724         cp = hashalgs = smalloc(n);
 1725         for(h = hashtab;;){
 1726                 strcpy(cp, h->name);
 1727                 cp += strlen(h->name);
 1728                 h++;
 1729                 if(h->name == nil)
 1730                         break;
 1731                 *cp++ = ' ';
 1732         }
 1733         *cp = 0;
 1734 }
 1735 
 1736 Dev tlsdevtab = {
 1737         'a',
 1738         "tls",
 1739 
 1740         devreset,
 1741         tlsinit,
 1742         devshutdown,
 1743         tlsattach,
 1744         tlswalk,
 1745         tlsstat,
 1746         tlsopen,
 1747         devcreate,
 1748         tlsclose,
 1749         tlsread,
 1750         tlsbread,
 1751         tlswrite,
 1752         tlsbwrite,
 1753         devremove,
 1754         tlswstat,
 1755 };
 1756 
 1757 /* get channel associated with an fd */
 1758 static Chan*
 1759 buftochan(char *p)
 1760 {
 1761         Chan *c;
 1762         int fd;
 1763 
 1764         if(p == 0)
 1765                 error(Ebadarg);
 1766         fd = strtoul(p, 0, 0);
 1767         if(fd < 0)
 1768                 error(Ebadarg);
 1769         c = fdtochan(fd, -1, 0, 1);     /* error check and inc ref */
 1770         return c;
 1771 }
 1772 
 1773 static void
 1774 sendAlert(TlsRec *tr, int err)
 1775 {
 1776         Block *b;
 1777         int i, fatal;
 1778         char *msg;
 1779 
 1780 if(tr->debug)pprint("sendAlert %d\n", err);
 1781         fatal = 1;
 1782         msg = "tls unknown alert";
 1783         for(i=0; i < nelem(tlserrs); i++) {
 1784                 if(tlserrs[i].err == err) {
 1785                         msg = tlserrs[i].msg;
 1786                         if(tr->version == SSL3Version)
 1787                                 err = tlserrs[i].sslerr;
 1788                         else
 1789                                 err = tlserrs[i].tlserr;
 1790                         fatal = tlserrs[i].fatal;
 1791                         break;
 1792                 }
 1793         }
 1794 
 1795         if(!waserror()){
 1796                 b = allocb(2);
 1797                 *b->wp++ = fatal + 1;
 1798                 *b->wp++ = err;
 1799                 if(fatal)
 1800                         tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose);
 1801                 tlsrecwrite(tr, RAlert, b);
 1802                 poperror();
 1803         }
 1804         if(fatal)
 1805                 tlsError(tr, msg);
 1806 }
 1807 
 1808 static void
 1809 tlsError(TlsRec *tr, char *msg)
 1810 {
 1811         int s;
 1812 
 1813 if(tr->debug)pprint("tleError %s\n", msg);
 1814         lock(&tr->statelk);
 1815         s = tr->state;
 1816         tr->state = SError;
 1817         if(s != SError){
 1818                 strncpy(tr->err, msg, ERRMAX - 1);
 1819                 tr->err[ERRMAX - 1] = '\0';
 1820         }
 1821         unlock(&tr->statelk);
 1822         if(s != SError)
 1823                 alertHand(tr, msg);
 1824 }
 1825 
 1826 static void
 1827 tlsSetState(TlsRec *tr, int new, int old)
 1828 {
 1829         lock(&tr->statelk);
 1830         if(tr->state & old)
 1831                 tr->state = new;
 1832         unlock(&tr->statelk);
 1833 }
 1834 
 1835 /* hand up a digest connection */
 1836 static void
 1837 tlshangup(TlsRec *tr)
 1838 {
 1839         Block *b;
 1840 
 1841         qlock(&tr->in.io);
 1842         for(b = tr->processed; b; b = tr->processed){
 1843                 tr->processed = b->next;
 1844                 freeb(b);
 1845         }
 1846         if(tr->unprocessed != nil){
 1847                 freeb(tr->unprocessed);
 1848                 tr->unprocessed = nil;
 1849         }
 1850         qunlock(&tr->in.io);
 1851 
 1852         tlsSetState(tr, SClosed, ~0);
 1853 }
 1854 
 1855 static TlsRec*
 1856 newtls(Chan *ch)
 1857 {
 1858         TlsRec **pp, **ep, **np;
 1859         char **nmp;
 1860         int t, newmax;
 1861 
 1862         if(waserror()) {
 1863                 unlock(&tdlock);
 1864                 nexterror();
 1865         }
 1866         lock(&tdlock);
 1867         ep = &tlsdevs[maxtlsdevs];
 1868         for(pp = tlsdevs; pp < ep; pp++)
 1869                 if(*pp == nil)
 1870                         break;
 1871         if(pp >= ep) {
 1872                 if(maxtlsdevs >= MaxTlsDevs) {
 1873                         unlock(&tdlock);
 1874                         poperror();
 1875                         return nil;
 1876                 }
 1877                 newmax = 2 * maxtlsdevs;
 1878                 if(newmax > MaxTlsDevs)
 1879                         newmax = MaxTlsDevs;
 1880                 np = smalloc(sizeof(TlsRec*) * newmax);
 1881                 memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs);
 1882                 tlsdevs = np;
 1883                 pp = &tlsdevs[maxtlsdevs];
 1884                 memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs));
 1885 
 1886                 nmp = smalloc(sizeof *nmp * newmax);
 1887                 memmove(nmp, trnames, sizeof *nmp * maxtlsdevs);
 1888                 trnames = nmp;
 1889 
 1890                 maxtlsdevs = newmax;
 1891         }
 1892         *pp = mktlsrec();
 1893         if(pp - tlsdevs >= tdhiwat)
 1894                 tdhiwat++;
 1895         t = TYPE(ch->qid);
 1896         if(t == Qclonus)
 1897                 t = Qctl;
 1898         ch->qid.path = QID(pp - tlsdevs, t);
 1899         ch->qid.vers = 0;
 1900         unlock(&tdlock);
 1901         poperror();
 1902         return *pp;
 1903 }
 1904 
 1905 static TlsRec *
 1906 mktlsrec(void)
 1907 {
 1908         TlsRec *tr;
 1909 
 1910         tr = mallocz(sizeof(*tr), 1);
 1911         if(tr == nil)
 1912                 error(Enomem);
 1913         tr->state = SClosed;
 1914         tr->ref = 1;
 1915         kstrdup(&tr->user, up->user);
 1916         tr->perm = 0660;
 1917         return tr;
 1918 }
 1919 
 1920 static char*
 1921 tlsstate(int s)
 1922 {
 1923         switch(s){
 1924         case SHandshake:
 1925                 return "Handshaking";
 1926         case SOpen:
 1927                 return "Established";
 1928         case SRClose:
 1929                 return "RemoteClosed";
 1930         case SLClose:
 1931                 return "LocalClosed";
 1932         case SAlert:
 1933                 return "Alerting";
 1934         case SError:
 1935                 return "Errored";
 1936         case SClosed:
 1937                 return "Closed";
 1938         }
 1939         return "Unknown";
 1940 }
 1941 
 1942 static void
 1943 freeSec(Secret *s)
 1944 {
 1945         if(s != nil){
 1946                 free(s->enckey);
 1947                 free(s);
 1948         }
 1949 }
 1950 
 1951 static int
 1952 noenc(Secret *, uchar *, int n)
 1953 {
 1954         return n;
 1955 }
 1956 
 1957 static int
 1958 rc4enc(Secret *sec, uchar *buf, int n)
 1959 {
 1960         rc4(sec->enckey, buf, n);
 1961         return n;
 1962 }
 1963 
 1964 static int
 1965 tlsunpad(uchar *buf, int n, int block)
 1966 {
 1967         int pad, nn;
 1968 
 1969         pad = buf[n - 1];
 1970         nn = n - 1 - pad;
 1971         if(nn <= 0 || n % block)
 1972                 return -1;
 1973         while(--n > nn)
 1974                 if(pad != buf[n - 1])
 1975                         return -1;
 1976         return nn;
 1977 }
 1978 
 1979 static int
 1980 sslunpad(uchar *buf, int n, int block)
 1981 {
 1982         int pad, nn;
 1983 
 1984         pad = buf[n - 1];
 1985         nn = n - 1 - pad;
 1986         if(nn <= 0 || n % block)
 1987                 return -1;
 1988         return nn;
 1989 }
 1990 
 1991 static int
 1992 blockpad(uchar *buf, int n, int block)
 1993 {
 1994         int pad, nn;
 1995 
 1996         nn = n + block;
 1997         nn -= nn % block;
 1998         pad = nn - (n + 1);
 1999         while(n < nn)
 2000                 buf[n++] = pad;
 2001         return nn;
 2002 }
 2003                 
 2004 static int
 2005 des3enc(Secret *sec, uchar *buf, int n)
 2006 {
 2007         n = blockpad(buf, n, 8);
 2008         des3CBCencrypt(buf, n, sec->enckey);
 2009         return n;
 2010 }
 2011 
 2012 static int
 2013 des3dec(Secret *sec, uchar *buf, int n)
 2014 {
 2015         des3CBCdecrypt(buf, n, sec->enckey);
 2016         return (*sec->unpad)(buf, n, 8);
 2017 }
 2018 static DigestState*
 2019 nomac(uchar *, ulong, uchar *, ulong, uchar *, DigestState *)
 2020 {
 2021         return nil;
 2022 }
 2023 
 2024 /*
 2025  * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
 2026  */
 2027 static DigestState*
 2028 sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
 2029         DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
 2030 {
 2031         int i;
 2032         uchar pad[48], innerdigest[20];
 2033 
 2034         if(xlen > sizeof(innerdigest)
 2035         || padlen > sizeof(pad))
 2036                 return nil;
 2037 
 2038         if(klen>64)
 2039                 return nil;
 2040 
 2041         /* first time through */
 2042         if(s == nil){
 2043                 for(i=0; i<padlen; i++)
 2044                         pad[i] = 0x36;
 2045                 s = (*x)(key, klen, nil, nil);
 2046                 s = (*x)(pad, padlen, nil, s);
 2047                 if(s == nil)
 2048                         return nil;
 2049         }
 2050 
 2051         s = (*x)(p, len, nil, s);
 2052         if(digest == nil)
 2053                 return s;
 2054 
 2055         /* last time through */
 2056         for(i=0; i<padlen; i++)
 2057                 pad[i] = 0x5c;
 2058         (*x)(nil, 0, innerdigest, s);
 2059         s = (*x)(key, klen, nil, nil);
 2060         s = (*x)(pad, padlen, nil, s);
 2061         (*x)(innerdigest, xlen, digest, s);
 2062         return nil;
 2063 }
 2064 
 2065 static DigestState*
 2066 sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
 2067 {
 2068         return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
 2069 }
 2070 
 2071 static DigestState*
 2072 sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
 2073 {
 2074         return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
 2075 }
 2076 
 2077 static void
 2078 sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
 2079 {
 2080         DigestState *s;
 2081         uchar buf[11];
 2082 
 2083         memmove(buf, seq, 8);
 2084         buf[8] = header[0];
 2085         buf[9] = header[3];
 2086         buf[10] = header[4];
 2087 
 2088         s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0);
 2089         (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
 2090 }
 2091 
 2092 static void
 2093 tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
 2094 {
 2095         DigestState *s;
 2096         uchar buf[13];
 2097 
 2098         memmove(buf, seq, 8);
 2099         memmove(&buf[8], header, 5);
 2100 
 2101         s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0);
 2102         (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
 2103 }
 2104 
 2105 static void
 2106 put32(uchar *p, u32int x)
 2107 {
 2108         p[0] = x>>24;
 2109         p[1] = x>>16;
 2110         p[2] = x>>8;
 2111         p[3] = x;
 2112 }
 2113 
 2114 static void
 2115 put64(uchar *p, vlong x)
 2116 {
 2117         put32(p, (u32int)(x >> 32));
 2118         put32(p+4, (u32int)x);
 2119 }
 2120 
 2121 static void
 2122 put24(uchar *p, int x)
 2123 {
 2124         p[0] = x>>16;
 2125         p[1] = x>>8;
 2126         p[2] = x;
 2127 }
 2128 
 2129 static void
 2130 put16(uchar *p, int x)
 2131 {
 2132         p[0] = x>>8;
 2133         p[1] = x;
 2134 }
 2135 
 2136 static u32int
 2137 get32(uchar *p)
 2138 {
 2139         return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
 2140 }
 2141 
 2142 static int
 2143 get16(uchar *p)
 2144 {
 2145         return (p[0]<<8)|p[1];
 2146 }
 2147 
 2148 static char *charmap = "0123456789abcdef";
 2149 
 2150 static void
 2151 pdump(int len, void *a, char *tag)
 2152 {
 2153         uchar *p;
 2154         int i;
 2155         char buf[65+32];
 2156         char *q;
 2157 
 2158         p = a;
 2159         strcpy(buf, tag);
 2160         while(len > 0){
 2161                 q = buf + strlen(tag);
 2162                 for(i = 0; len > 0 && i < 32; i++){
 2163                         if(*p >= ' ' && *p < 0x7f){
 2164                                 *q++ = ' ';
 2165                                 *q++ = *p;
 2166                         } else {
 2167                                 *q++ = charmap[*p>>4];
 2168                                 *q++ = charmap[*p & 0xf];
 2169                         }
 2170                         len--;
 2171                         p++;
 2172                 }
 2173                 *q = 0;
 2174 
 2175                 if(len > 0)
 2176                         pprint("%s...\n", buf);
 2177                 else
 2178                         pprint("%s\n", buf);
 2179         }
 2180 }

Cache object: e02e387c3583d011dbda58a4b9853e0b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.