1. add the curve x25519 to tls, both client and server. it's more faster, immune to timing attacks by design, does not require verifying if the public key is valid, etc etc. server-side has to check if the client supports the curve, so a new function has been introduced to parse the client's extensions. 2. reject weak dhe primes that can be easily cracked with the number field sieve algorithm. this avoids attacks like logjam. 3. stop putting unix time to the first 4 bytes of client/ server random. it can allow fingerprinting, tls 1.3 doesn't recommend it any more and there was a draft to deprecate this behaviour earlier.[1] 4. simply prf code, remove useless cipher enums. [1] https://datatracker.ietf.org/doc/html/draft-mathewson-no-gmtunixtime-00
Unified · Split
| @@ -66,18 +66,20 @@ struct TlsSec { · 65 unmodified lines | |||
| 66 | int psklen; | 66 | int psklen; |
| 67 | int clientVers; // version in ClientHello | 67 | int clientVers; // version in ClientHello |
| 68 | uchar sec[MasterSecretSize]; // master secret | 68 | uchar sec[MasterSecretSize]; // master secret |
| 69 | uchar crandom[RandomSize]; // client random | ||
| 70 | uchar srandom[RandomSize]; // server random | 69 | uchar srandom[RandomSize]; // server random |
| 70 | uchar crandom[RandomSize]; // client random | ||
| 71 | 71 | ||
| 72 | Namedcurve *nc; // selected curve for ECDHE | ||
| 72 | // diffie hellman state | 73 | // diffie hellman state |
| 73 | DHstate dh; | 74 | DHstate dh; |
| 74 | struct { | 75 | struct { |
| 75 | ECdomain dom; | 76 | ECdomain dom; |
| 76 | ECpriv Q; | 77 | ECpriv Q; |
| 77 | } ec; | 78 | } ec; |
| 79 | uchar X[32]; | ||
| 78 | 80 | ||
| 79 | // byte generation and handshake checksum | 81 | // byte generation and handshake checksum |
| 80 | void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int, uchar*, int); | 82 | void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int); |
| 81 | void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int); | 83 | void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int); |
| 82 | int nfin; | 84 | int nfin; |
| 83 | }; | 85 | }; |
| @@ -107,7 +109,7 @@ typedef struct Msg{ · 23 unmodified lines | |||
| 107 | int tag; | 109 | int tag; |
| 108 | union { | 110 | union { |
| 109 | struct { | 111 | struct { |
| 110 | int version; | 112 | int version; |
| 111 | uchar random[RandomSize]; | 113 | uchar random[RandomSize]; |
| 112 | Bytes* sid; | 114 | Bytes* sid; |
| 113 | Ints* ciphers; | 115 | Ints* ciphers; |
| @@ -115,7 +117,7 @@ typedef struct Msg{ · 1 unmodified line | |||
| 115 | Bytes* extensions; | 117 | Bytes* extensions; |
| 116 | } clientHello; | 118 | } clientHello; |
| 117 | struct { | 119 | struct { |
| 118 | int version; | 120 | int version; |
| 119 | uchar random[RandomSize]; | 121 | uchar random[RandomSize]; |
| 120 | Bytes* sid; | 122 | Bytes* sid; |
| 121 | int cipher; | 123 | int cipher; |
| @@ -214,79 +216,36 @@ enum { · 92 unmodified lines | |||
| 214 | 216 | ||
| 215 | // cipher suites | 217 | // cipher suites |
| 216 | enum { | 218 | enum { |
| 217 | TLS_NULL_WITH_NULL_NULL = 0x0000, | ||
| 218 | TLS_RSA_WITH_NULL_MD5 = 0x0001, | ||
| 219 | TLS_RSA_WITH_NULL_SHA = 0x0002, | ||
| 220 | TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003, | ||
| 221 | TLS_RSA_WITH_RC4_128_MD5 = 0x0004, | ||
| 222 | TLS_RSA_WITH_RC4_128_SHA = 0x0005, | ||
| 223 | TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0X0006, | ||
| 224 | TLS_RSA_WITH_IDEA_CBC_SHA = 0X0007, | ||
| 225 | TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0X0008, | ||
| 226 | TLS_RSA_WITH_DES_CBC_SHA = 0X0009, | ||
| 227 | TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0X000A, | 219 | TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0X000A, |
| 228 | TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0X000B, | ||
| 229 | TLS_DH_DSS_WITH_DES_CBC_SHA = 0X000C, | ||
| 230 | TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0X000D, | ||
| 231 | TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0X000E, | ||
| 232 | TLS_DH_RSA_WITH_DES_CBC_SHA = 0X000F, | ||
| 233 | TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0X0010, | ||
| 234 | TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0X0011, | ||
| 235 | TLS_DHE_DSS_WITH_DES_CBC_SHA = 0X0012, | ||
| 236 | TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0X0013, // ZZZ must be implemented for tls1.0 compliance | ||
| 237 | TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0X0014, | ||
| 238 | TLS_DHE_RSA_WITH_DES_CBC_SHA = 0X0015, | ||
| 239 | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0X0016, | 220 | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0X0016, |
| 240 | TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017, | 221 | |
| 241 | TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018, | 222 | TLS_RSA_WITH_AES_128_CBC_SHA = 0X002F, |
| 242 | TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0X0019, | ||
| 243 | TLS_DH_anon_WITH_DES_CBC_SHA = 0X001A, | ||
| 244 | TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0X001B, | ||
| 245 | TLS_RSA_WITH_AES_128_CBC_SHA = 0X002F, // aes, aka rijndael with 128 bit blocks | ||
| 246 | TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0X0030, | ||
| 247 | TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0X0031, | ||
| 248 | TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0X0032, | ||
| 249 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0X0033, | 223 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0X0033, |
| 250 | TLS_DH_anon_WITH_AES_128_CBC_SHA = 0X0034, | ||
| 251 | TLS_RSA_WITH_AES_256_CBC_SHA = 0X0035, | 224 | TLS_RSA_WITH_AES_256_CBC_SHA = 0X0035, |
| 252 | TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0X0036, | ||
| 253 | TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0X0037, | ||
| 254 | TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0X0038, | ||
| 255 | TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0X0039, | 225 | TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0X0039, |
| 256 | TLS_DH_anon_WITH_AES_256_CBC_SHA = 0X003A, | ||
| 257 | TLS_RSA_WITH_AES_128_CBC_SHA256 = 0X003C, | 226 | TLS_RSA_WITH_AES_128_CBC_SHA256 = 0X003C, |
| 258 | TLS_RSA_WITH_AES_256_CBC_SHA256 = 0X003D, | 227 | TLS_RSA_WITH_AES_256_CBC_SHA256 = 0X003D, |
| 259 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0X0067, | 228 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0X0067, |
| 260 | 229 | ||
| 261 | TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C, | 230 | TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C, |
| 262 | TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D, | ||
| 263 | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E, | 231 | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E, |
| 264 | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F, | ||
| 265 | TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0, | ||
| 266 | TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1, | ||
| 267 | TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2, | ||
| 268 | TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3, | ||
| 269 | TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4, | ||
| 270 | TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5, | ||
| 271 | TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6, | ||
| 272 | TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7, | ||
| 273 | |||
| 274 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B, | ||
| 275 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F, | ||
| 276 | 232 | ||
| 277 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, | 233 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, |
| 278 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, | 234 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, |
| 279 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027, | ||
| 280 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023, | 235 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023, |
| 236 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027, | ||
| 281 | 237 | ||
| 282 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCA8, | 238 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B, |
| 283 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCCA9, | 239 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F, |
| 284 | TLS_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCAA, | ||
| 285 | 240 | ||
| 286 | GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC13, | 241 | GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC13, |
| 287 | GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCC14, | 242 | GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCC14, |
| 288 | GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC15, | 243 | GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCC15, |
| 289 | 244 | ||
| 245 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCA8, | ||
| 246 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 0xCCA9, | ||
| 247 | TLS_DHE_RSA_WITH_CHACHA20_POLY1305 = 0xCCAA, | ||
| 248 | |||
| 290 | TLS_PSK_WITH_CHACHA20_POLY1305 = 0xCCAB, | 249 | TLS_PSK_WITH_CHACHA20_POLY1305 = 0xCCAB, |
| 291 | TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE, | 250 | TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE, |
| 292 | TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C, | 251 | TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C, |
| @@ -300,6 +259,20 @@ enum { · 7 unmodified lines | |||
| 300 | CompressionMax | 259 | CompressionMax |
| 301 | }; | 260 | }; |
| 302 | 261 | ||
| 262 | |||
| 263 | // curves | ||
| 264 | enum { | ||
| 265 | X25519 = 0x001d, | ||
| 266 | }; | ||
| 267 | |||
| 268 | // extensions | ||
| 269 | enum { | ||
| 270 | Extsni = 0x0000, | ||
| 271 | Extec = 0x000a, | ||
| 272 | Extecp = 0x000b, | ||
| 273 | Extsigalgs = 0x000d, | ||
| 274 | }; | ||
| 275 | |||
| 303 | static Algs cipherAlgs[] = { | 276 | static Algs cipherAlgs[] = { |
| 304 | // ECDHE-ECDSA | 277 | // ECDHE-ECDSA |
| 305 | {"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305}, | 278 | {"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305}, |
| @@ -343,6 +316,7 @@ static uchar compressors[] = { · 37 unmodified lines | |||
| 343 | }; | 316 | }; |
| 344 | 317 | ||
| 345 | static Namedcurve namedcurves[] = { | 318 | static Namedcurve namedcurves[] = { |
| 319 | X25519, nil, | ||
| 346 | 0x0017, secp256r1, | 320 | 0x0017, secp256r1, |
| 347 | 0x0018, secp384r1, | 321 | 0x0018, secp384r1, |
| 348 | }; | 322 | }; |
| @@ -401,7 +375,7 @@ static int isPSK(int tlsid); · 52 unmodified lines | |||
| 401 | static int isECDSA(int tlsid); | 375 | static int isECDSA(int tlsid); |
| 402 | 376 | ||
| 403 | static int setAlgs(TlsConnection *c, int a); | 377 | static int setAlgs(TlsConnection *c, int a); |
| 404 | static int okCipher(Ints *cv, int ispsk); | 378 | static int okCipher(Ints *cv, int ispsk, int canec); |
| 405 | static int okCompression(Bytes *cv); | 379 | static int okCompression(Bytes *cv); |
| 406 | static int initCiphers(void); | 380 | static int initCiphers(void); |
| 407 | static Ints* makeciphers(int ispsk); | 381 | static Ints* makeciphers(int ispsk); |
| @@ -412,7 +386,7 @@ static void factotum_rsa_close(AuthRpc *rpc); · 4 unmodified lines | |||
| 412 | 386 | ||
| 413 | static void tlsSecInits(TlsSec *sec, int cvers, uchar *crandom); | 387 | static void tlsSecInits(TlsSec *sec, int cvers, uchar *crandom); |
| 414 | static int tlsSecRSAs(TlsSec *sec, Bytes *epm); | 388 | static int tlsSecRSAs(TlsSec *sec, Bytes *epm); |
| 415 | static Bytes* tlsSecECDHEs1(TlsSec *sec, Namedcurve *nc); | 389 | static Bytes* tlsSecECDHEs1(TlsSec *sec); |
| 416 | static int tlsSecECDHEs2(TlsSec *sec, Bytes *Yc); | 390 | static int tlsSecECDHEs2(TlsSec *sec, Bytes *Yc); |
| 417 | static void tlsSecInitc(TlsSec *sec, int cvers); | 391 | static void tlsSecInitc(TlsSec *sec, int cvers); |
| 418 | static Bytes* tlsSecRSAc(TlsSec *sec, uchar *cert, int ncert); | 392 | static Bytes* tlsSecRSAc(TlsSec *sec, uchar *cert, int ncert); |
| @@ -458,12 +432,13 @@ tlsServer(int fd, TLSconn *conn) · 39 unmodified lines | |||
| 458 | { | 432 | { |
| 459 | char buf[8]; | 433 | char buf[8]; |
| 460 | char dname[64]; | 434 | char dname[64]; |
| 435 | uchar seed[2*RandomSize]; | ||
| 461 | int n, data, ctl, hand; | 436 | int n, data, ctl, hand; |
| 462 | TlsConnection *tls; | 437 | TlsConnection *tls; |
| 463 | 438 | ||
| 464 | if(conn == nil) | 439 | if(conn == nil) |
| 465 | return -1; | 440 | return -1; |
| 466 | ctl = open("#a/tls/clone", ORDWR); | 441 | ctl = open("#a/tls/clone", ORDWR|OCEXEC); |
| 467 | if(ctl < 0) | 442 | if(ctl < 0) |
| 468 | return -1; | 443 | return -1; |
| 469 | n = read(ctl, buf, sizeof(buf)-1); | 444 | n = read(ctl, buf, sizeof(buf)-1); |
| @@ -474,7 +449,7 @@ tlsServer(int fd, TLSconn *conn) · 4 unmodified lines | |||
| 474 | buf[n] = 0; | 449 | buf[n] = 0; |
| 475 | snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf); | 450 | snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf); |
| 476 | snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); | 451 | snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); |
| 477 | hand = open(dname, ORDWR); | 452 | hand = open(dname, ORDWR|OCEXEC); |
| 478 | if(hand < 0){ | 453 | if(hand < 0){ |
| 479 | close(ctl); | 454 | close(ctl); |
| 480 | return -1; | 455 | return -1; |
| @@ -502,13 +477,15 @@ tlsServer(int fd, TLSconn *conn) · 21 unmodified lines | |||
| 502 | conn->sessionID = nil; | 477 | conn->sessionID = nil; |
| 503 | if(conn->sessionKey != nil | 478 | if(conn->sessionKey != nil |
| 504 | && conn->sessionType != nil | 479 | && conn->sessionType != nil |
| 505 | && strcmp(conn->sessionType, "ttls") == 0) | 480 | && strcmp(conn->sessionType, "ttls") == 0){ |
| 481 | memmove(seed, tls->sec->crandom, RandomSize); | ||
| 482 | memmove(seed+RandomSize, tls->sec->srandom, RandomSize); | ||
| 506 | tls->sec->prf( | 483 | tls->sec->prf( |
| 507 | conn->sessionKey, conn->sessionKeylen, | 484 | conn->sessionKey, conn->sessionKeylen, |
| 508 | tls->sec->sec, MasterSecretSize, | 485 | tls->sec->sec, MasterSecretSize, |
| 509 | conn->sessionConst, | 486 | conn->sessionConst, |
| 510 | tls->sec->crandom, RandomSize, | 487 | seed, sizeof(seed)); |
| 511 | tls->sec->srandom, RandomSize); | 488 | } |
| 512 | tlsConnectionFree(tls); | 489 | tlsConnectionFree(tls); |
| 513 | close(fd); | 490 | close(fd); |
| 514 | return data; | 491 | return data; |
| @@ -530,7 +507,7 @@ tlsClientExtensions(TLSconn *conn, int *plen) · 15 unmodified lines | |||
| 530 | b = erealloc(b, m + 2+2+2+1+2+n); | 507 | b = erealloc(b, m + 2+2+2+1+2+n); |
| 531 | p = b + m; | 508 | p = b + m; |
| 532 | 509 | ||
| 533 | put16(p, 0), p += 2; /* Type: server_name */ | 510 | put16(p, Extsni), p += 2; /* Type: server_name */ |
| 534 | put16(p, 2+1+2+n), p += 2; /* Length */ | 511 | put16(p, 2+1+2+n), p += 2; /* Length */ |
| 535 | put16(p, 1+2+n), p += 2; /* Server Name list length */ | 512 | put16(p, 1+2+n), p += 2; /* Server Name list length */ |
| 536 | *p++ = 0; /* Server Name Type: host_name */ | 513 | *p++ = 0; /* Server Name Type: host_name */ |
| @@ -539,26 +516,26 @@ tlsClientExtensions(TLSconn *conn, int *plen) · 2 unmodified lines | |||
| 539 | p += n; | 516 | p += n; |
| 540 | } | 517 | } |
| 541 | 518 | ||
| 542 | // ECDHE | 519 | // Elliptic Curves (also called Supported Groups) |
| 543 | if(ProtocolVersion >= TLS10Version){ | 520 | if(ProtocolVersion >= TLS10Version){ |
| 544 | m = p - b; | 521 | m = p - b; |
| 545 | b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats)); | 522 | b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats)); |
| 546 | p = b + m; | 523 | p = b + m; |
| 547 | 524 | ||
| 548 | n = nelem(namedcurves); | 525 | n = nelem(namedcurves); |
| 549 | put16(p, 0x000a), p += 2; /* Type: elliptic_curves */ | 526 | put16(p, Extec), p += 2; /* Type: elliptic_curves / supported_groups */ |
| 550 | put16(p, (n+1)*2), p += 2; /* Length */ | 527 | put16(p, (n+1)*2), p += 2; /* Length */ |
| 551 | put16(p, n*2), p += 2; /* Elliptic Curves Length */ | 528 | put16(p, n*2), p += 2; /* Elliptic Curves Length */ |
| 552 | for(i=0; i < n; i++){ /* Elliptic curves */ | 529 | for(i=0; i < n; i++){ /* Elliptic Curves */ |
| 553 | put16(p, namedcurves[i].tlsid); | 530 | put16(p, namedcurves[i].tlsid); |
| 554 | p += 2; | 531 | p += 2; |
| 555 | } | 532 | } |
| 556 | 533 | ||
| 557 | n = nelem(pointformats); | 534 | n = nelem(pointformats); |
| 558 | put16(p, 0x000b), p += 2; /* Type: ec_point_formats */ | 535 | put16(p, Extecp), p += 2; /* Type: ec_point_formats */ |
| 559 | put16(p, n+1), p += 2; /* Length */ | 536 | put16(p, n+1), p += 2; /* Length */ |
| 560 | *p++ = n; /* EC point formats Length */ | 537 | *p++ = n; /* EC point formats Length */ |
| 561 | for(i=0; i < n; i++) /* Elliptic curves point formats */ | 538 | for(i=0; i < n; i++) /* EC point formats */ |
| 562 | *p++ = pointformats[i]; | 539 | *p++ = pointformats[i]; |
| 563 | } | 540 | } |
| 564 | 541 | ||
| @@ -570,7 +547,7 @@ tlsClientExtensions(TLSconn *conn, int *plen) · 5 unmodified lines | |||
| 570 | b = erealloc(b, m + 2+2+2+n*2); | 547 | b = erealloc(b, m + 2+2+2+n*2); |
| 571 | p = b + m; | 548 | p = b + m; |
| 572 | 549 | ||
| 573 | put16(p, 0x000d), p += 2; | 550 | put16(p, Extsigalgs), p += 2; |
| 574 | put16(p, n*2 + 2), p += 2; | 551 | put16(p, n*2 + 2), p += 2; |
| 575 | put16(p, n*2), p += 2; | 552 | put16(p, n*2), p += 2; |
| 576 | for(i=0; i < n; i++){ | 553 | for(i=0; i < n; i++){ |
| @@ -590,13 +567,14 @@ tlsClient(int fd, TLSconn *conn) · 13 unmodified lines | |||
| 590 | { | 567 | { |
| 591 | char buf[8]; | 568 | char buf[8]; |
| 592 | char dname[64]; | 569 | char dname[64]; |
| 570 | uchar seed[2*RandomSize]; | ||
| 593 | int n, data, ctl, hand; | 571 | int n, data, ctl, hand; |
| 594 | TlsConnection *tls; | 572 | TlsConnection *tls; |
| 595 | uchar *ext; | 573 | uchar *ext; |
| 596 | 574 | ||
| 597 | if(conn == nil) | 575 | if(conn == nil) |
| 598 | return -1; | 576 | return -1; |
| 599 | ctl = open("#a/tls/clone", ORDWR); | 577 | ctl = open("#a/tls/clone", ORDWR|OCEXEC); |
| 600 | if(ctl < 0) | 578 | if(ctl < 0) |
| 601 | return -1; | 579 | return -1; |
| 602 | n = read(ctl, buf, sizeof(buf)-1); | 580 | n = read(ctl, buf, sizeof(buf)-1); |
| @@ -607,7 +585,7 @@ tlsClient(int fd, TLSconn *conn) · 4 unmodified lines | |||
| 607 | buf[n] = 0; | 585 | buf[n] = 0; |
| 608 | snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf); | 586 | snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf); |
| 609 | snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); | 587 | snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf); |
| 610 | hand = open(dname, ORDWR); | 588 | hand = open(dname, ORDWR|OCEXEC); |
| 611 | if(hand < 0){ | 589 | if(hand < 0){ |
| 612 | close(ctl); | 590 | close(ctl); |
| 613 | return -1; | 591 | return -1; |
| @@ -645,13 +623,15 @@ tlsClient(int fd, TLSconn *conn) · 31 unmodified lines | |||
| 645 | conn->sessionID = nil; | 623 | conn->sessionID = nil; |
| 646 | if(conn->sessionKey != nil | 624 | if(conn->sessionKey != nil |
| 647 | && conn->sessionType != nil | 625 | && conn->sessionType != nil |
| 648 | && strcmp(conn->sessionType, "ttls") == 0) | 626 | && strcmp(conn->sessionType, "ttls") == 0){ |
| 627 | memmove(seed, tls->sec->crandom, RandomSize); | ||
| 628 | memmove(seed+RandomSize, tls->sec->srandom, RandomSize); | ||
| 649 | tls->sec->prf( | 629 | tls->sec->prf( |
| 650 | conn->sessionKey, conn->sessionKeylen, | 630 | conn->sessionKey, conn->sessionKeylen, |
| 651 | tls->sec->sec, MasterSecretSize, | 631 | tls->sec->sec, MasterSecretSize, |
| 652 | conn->sessionConst, | 632 | conn->sessionConst, |
| 653 | tls->sec->crandom, RandomSize, | 633 | seed, sizeof(seed)); |
| 654 | tls->sec->srandom, RandomSize); | 634 | } |
| 655 | tlsConnectionFree(tls); | 635 | tlsConnectionFree(tls); |
| 656 | close(fd); | 636 | close(fd); |
| 657 | return data; | 637 | return data; |
| @@ -669,6 +649,53 @@ countchain(PEMChain *p) · 11 unmodified lines | |||
| 669 | return i; | 649 | return i; |
| 670 | } | 650 | } |
| 671 | 651 | ||
| 652 | static int | ||
| 653 | checkClientExtensions(TlsConnection *c, Bytes *ext) | ||
| 654 | { | ||
| 655 | uchar *p, *e; | ||
| 656 | int i, j, n; | ||
| 657 | |||
| 658 | p = ext->data; | ||
| 659 | e = p+ext->len; | ||
| 660 | while(p < e){ | ||
| 661 | if(e-p < 2) | ||
| 662 | goto Short; | ||
| 663 | switch(get16(p)){ | ||
| 664 | case Extec: | ||
| 665 | p += 2; | ||
| 666 | n = get16(p); | ||
| 667 | if(e-p < n || n < 2) | ||
| 668 | goto Short; | ||
| 669 | p += 2; | ||
| 670 | n = get16(p); | ||
| 671 | p += 2; | ||
| 672 | if(e-p < n || n & 1 || n == 0) | ||
| 673 | goto Short; | ||
| 674 | for(i = 0; i < nelem(namedcurves) && c->sec->nc == nil; i++) | ||
| 675 | for(j = 0; j < n; j += 2) | ||
| 676 | if(namedcurves[i].tlsid == get16(p+j)){ | ||
| 677 | c->sec->nc = &namedcurves[i]; | ||
| 678 | break; | ||
| 679 | } | ||
| 680 | p += n; | ||
| 681 | break; | ||
| 682 | default: | ||
| 683 | p += 2; | ||
| 684 | n = get16(p); | ||
| 685 | p += 2; | ||
| 686 | if(e-p < n) | ||
| 687 | goto Short; | ||
| 688 | p += n; | ||
| 689 | break; | ||
| 690 | } | ||
| 691 | } | ||
| 692 | |||
| 693 | return 0; | ||
| 694 | Short: | ||
| 695 | tlsError(c, EDecodeError, "clienthello extensions has invalid length"); | ||
| 696 | return -1; | ||
| 697 | } | ||
| 698 | |||
| 672 | static TlsConnection * | 699 | static TlsConnection * |
| 673 | tlsServer2(int ctl, int hand, | 700 | tlsServer2(int ctl, int hand, |
| 674 | uchar *cert, int certlen, | 701 | uchar *cert, int certlen, |
| @@ -712,19 +739,6 @@ tlsServer2(int ctl, int hand, · 37 unmodified lines | |||
| 712 | tlsError(c, EInappropriateFallback, "inappropriate fallback"); | 739 | tlsError(c, EInappropriateFallback, "inappropriate fallback"); |
| 713 | goto Err; | 740 | goto Err; |
| 714 | } | 741 | } |
| 715 | cipher = okCipher(m.u.clientHello.ciphers, psklen > 0); | ||
| 716 | if(cipher < 0 || !setAlgs(c, cipher)) { | ||
| 717 | tlsError(c, EHandshakeFailure, "no matching cipher suite"); | ||
| 718 | goto Err; | ||
| 719 | } | ||
| 720 | compressor = okCompression(m.u.clientHello.compressors); | ||
| 721 | if(compressor < 0) { | ||
| 722 | tlsError(c, EHandshakeFailure, "no matching compressor"); | ||
| 723 | goto Err; | ||
| 724 | } | ||
| 725 | if(trace) | ||
| 726 | trace(" cipher %x, compressor %x\n", cipher, compressor); | ||
| 727 | |||
| 728 | tlsSecInits(c->sec, m.u.clientHello.version, m.u.clientHello.random); | 742 | tlsSecInits(c->sec, m.u.clientHello.version, m.u.clientHello.random); |
| 729 | tlsSecVers(c->sec, c->version); | 743 | tlsSecVers(c->sec, c->version); |
| 730 | if(psklen > 0){ | 744 | if(psklen > 0){ |
| @@ -744,6 +758,20 @@ tlsServer2(int ctl, int hand, · 13 unmodified lines | |||
| 744 | goto Err; | 758 | goto Err; |
| 745 | } | 759 | } |
| 746 | } | 760 | } |
| 761 | if(checkClientExtensions(c, m.u.clientHello.extensions) < 0) | ||
| 762 | goto Err; | ||
| 763 | cipher = okCipher(m.u.clientHello.ciphers, psklen > 0, c->sec->nc != nil); | ||
| 764 | if(cipher < 0 || !setAlgs(c, cipher)) { | ||
| 765 | tlsError(c, EHandshakeFailure, "no matching cipher suite"); | ||
| 766 | goto Err; | ||
| 767 | } | ||
| 768 | compressor = okCompression(m.u.clientHello.compressors); | ||
| 769 | if(compressor < 0) { | ||
| 770 | tlsError(c, EHandshakeFailure, "no matching compressor"); | ||
| 771 | goto Err; | ||
| 772 | } | ||
| 773 | if(trace) | ||
| 774 | trace(" cipher %x, compressor %x\n", cipher, compressor); | ||
| 747 | msgClear(&m); | 775 | msgClear(&m); |
| 748 | 776 | ||
| 749 | m.tag = HServerHello; | 777 | m.tag = HServerHello; |
| @@ -768,11 +796,9 @@ tlsServer2(int ctl, int hand, · 18 unmodified lines | |||
| 768 | } | 796 | } |
| 769 | 797 | ||
| 770 | if(isECDHE(cipher)){ | 798 | if(isECDHE(cipher)){ |
| 771 | Namedcurve *nc = &namedcurves[0]; /* secp256r1 */ | ||
| 772 | |||
| 773 | m.tag = HServerKeyExchange; | 799 | m.tag = HServerKeyExchange; |
| 774 | m.u.serverKeyExchange.curve = nc->tlsid; | 800 | m.u.serverKeyExchange.curve = c->sec->nc->tlsid; |
| 775 | m.u.serverKeyExchange.dh_parameters = tlsSecECDHEs1(c->sec, nc); | 801 | m.u.serverKeyExchange.dh_parameters = tlsSecECDHEs1(c->sec); |
| 776 | if(m.u.serverKeyExchange.dh_parameters == nil){ | 802 | if(m.u.serverKeyExchange.dh_parameters == nil){ |
| 777 | tlsError(c, EInternalError, "can't set DH parameters"); | 803 | tlsError(c, EInternalError, "can't set DH parameters"); |
| 778 | goto Err; | 804 | goto Err; |
| @@ -893,7 +919,9 @@ tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys) · 114 unmodified lines | |||
| 893 | 919 | ||
| 894 | if(p == nil || g == nil || Ys == nil) | 920 | if(p == nil || g == nil || Ys == nil) |
| 895 | return nil; | 921 | return nil; |
| 896 | 922 | // reject dh primes that is susceptible to logjam | |
| 923 | if(p->len <= 1024/8) | ||
| 924 | return nil; | ||
| 897 | Yc = nil; | 925 | Yc = nil; |
| 898 | P = bytestomp(p); | 926 | P = bytestomp(p); |
| 899 | G = bytestomp(g); | 927 | G = bytestomp(g); |
| @@ -924,49 +952,65 @@ Out: · 24 unmodified lines | |||
| 924 | static Bytes* | 952 | static Bytes* |
| 925 | tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys) | 953 | tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys) |
| 926 | { | 954 | { |
| 955 | static char zero[32] = {0}; | ||
| 927 | ECdomain *dom = &sec->ec.dom; | 956 | ECdomain *dom = &sec->ec.dom; |
| 928 | ECpriv *Q = &sec->ec.Q; | 957 | ECpriv *Q = &sec->ec.Q; |
| 929 | Namedcurve *nc; | ||
| 930 | ECpub *pub; | 958 | ECpub *pub; |
| 931 | ECpoint K; | 959 | ECpoint K; |
| 960 | Namedcurve *nc; | ||
| 932 | Bytes *Yc; | 961 | Bytes *Yc; |
| 962 | Bytes *Z; | ||
| 933 | int n; | 963 | int n; |
| 934 | 964 | ||
| 935 | if(Ys == nil) | 965 | if(Ys == nil) |
| 936 | return nil; | 966 | return nil; |
| 937 | for(nc = namedcurves; nc != &namedcurves[nelem(namedcurves)]; nc++) | ||
| 938 | if(nc->tlsid == curve) | ||
| 939 | goto Found; | ||
| 940 | return nil; | ||
| 941 | |||
| 942 | Found: | ||
| 943 | ecdominit(dom, nc->init); | ||
| 944 | pub = ecdecodepub(dom, Ys->data, Ys->len); | ||
| 945 | if(pub == nil) | ||
| 946 | return nil; | ||
| 947 | 967 | ||
| 948 | memset(Q, 0, sizeof(*Q)); | 968 | if(curve == X25519){ |
| 949 | Q->a.x = mpnew(0); | 969 | if(Ys->len != 32) |
| 950 | Q->a.y = mpnew(0); | 970 | return nil; |
| 951 | Q->d = mpnew(0); | 971 | Yc = newbytes(32); |
| 972 | curve25519_dh_new(sec->X, Yc->data); | ||
| 973 | Z = newbytes(32); | ||
| 974 | curve25519_dh_finish(sec->X, Ys->data, Z->data); | ||
| 975 | // rfc wants us to terminate the connection if | ||
| 976 | // shared secret == all zeroes. | ||
| 977 | if(tsmemcmp(Z->data, zero, Z->len) == 0){ | ||
| 978 | freebytes(Yc); | ||
| 979 | freebytes(Z); | ||
| 980 | return nil; | ||
| 981 | } | ||
| 982 | setMasterSecret(sec, Z); | ||
| 983 | }else{ | ||
| 984 | for(nc = namedcurves; nc->tlsid != curve; nc++) | ||
| 985 | if(nc == &namedcurves[nelem(namedcurves)]) | ||
| 986 | return nil; | ||
| 987 | ecdominit(dom, nc->init); | ||
| 988 | pub = ecdecodepub(dom, Ys->data, Ys->len); | ||
| 989 | if(pub == nil) | ||
| 990 | return nil; | ||
| 952 | 991 | ||
| 953 | memset(&K, 0, sizeof(K)); | 992 | memset(Q, 0, sizeof(*Q)); |
| 954 | K.x = mpnew(0); | 993 | Q->x = mpnew(0); |
| 955 | K.y = mpnew(0); | 994 | Q->y = mpnew(0); |
| 995 | Q->d = mpnew(0); | ||
| 956 | 996 | ||
| 957 | ecgen(dom, Q); | 997 | memset(&K, 0, sizeof(K)); |
| 958 | ecmul(dom, pub, Q->d, &K); | 998 | K.x = mpnew(0); |
| 999 | K.y = mpnew(0); | ||
| 959 | 1000 | ||
| 960 | n = (mpsignif(dom->p)+7)/8; | 1001 | ecgen(dom, Q); |
| 961 | setMasterSecret(sec, mptobytes(K.x, n)); | 1002 | ecmul(dom, pub, Q->d, &K); |
| 962 | Yc = newbytes(1 + 2*n); | ||
| 963 | Yc->len = ecencodepub(dom, (ECpub*)Q, Yc->data, Yc->len); | ||
| 964 | 1003 | ||
| 965 | mpfree(K.x); | 1004 | n = (mpsignif(dom->p)+7)/8; |
| 966 | mpfree(K.y); | 1005 | setMasterSecret(sec, mptobytes(K.x, n)); |
| 1006 | Yc = newbytes(1 + 2*n); | ||
| 1007 | Yc->len = ecencodepub(dom, Q, Yc->data, Yc->len); | ||
| 967 | 1008 | ||
| 968 | ecpubfree(pub); | 1009 | mpfree(K.x); |
| 1010 | mpfree(K.y); | ||
| 969 | 1011 | ||
| 1012 | ecpubfree(pub); | ||
| 1013 | } | ||
| 970 | return Yc; | 1014 | return Yc; |
| 971 | } | 1015 | } |
| 972 | 1016 | ||
| @@ -1049,7 +1093,6 @@ tlsClient2(int ctl, int hand, · 76 unmodified lines | |||
| 1049 | tlsError(c, EIllegalParameter, "invalid compression"); | 1093 | tlsError(c, EIllegalParameter, "invalid compression"); |
| 1050 | goto Err; | 1094 | goto Err; |
| 1051 | } | 1095 | } |
| 1052 | |||
| 1053 | dhx = isDHE(cipher) || isECDHE(cipher); | 1096 | dhx = isDHE(cipher) || isECDHE(cipher); |
| 1054 | if(!msgRecv(c, &m)) | 1097 | if(!msgRecv(c, &m)) |
| 1055 | goto Err; | 1098 | goto Err; |
| @@ -1790,8 +1833,7 @@ msgRecv(TlsConnection *c, Msg *m) · 734 unmodified lines | |||
| 1790 | goto Short; | 1833 | goto Short; |
| 1791 | Ok: | 1834 | Ok: |
| 1792 | if(c->trace) | 1835 | if(c->trace) |
| 1793 | c->trace("recv %s", msgPrint((char*)c->sendp, | 1836 | c->trace("recv %s", msgPrint((char*)c->sendp, &c->buf[sizeof(c->buf)] - c->sendp, m)); |
| 1794 | &c->buf[sizeof(c->buf)] - c->sendp, m)); | ||
| 1795 | return 1; | 1837 | return 1; |
| 1796 | Short: | 1838 | Short: |
| 1797 | tlsError(c, EDecodeError, "handshake message (%d) has invalid length", type); | 1839 | tlsError(c, EDecodeError, "handshake message (%d) has invalid length", type); |
| @@ -2042,8 +2084,8 @@ tlsConnectionFree(TlsConnection *c) · 244 unmodified lines | |||
| 2042 | 2084 | ||
| 2043 | dh_finish(&c->sec->dh, nil); | 2085 | dh_finish(&c->sec->dh, nil); |
| 2044 | 2086 | ||
| 2045 | mpfree(c->sec->ec.Q.a.x); | 2087 | mpfree(c->sec->ec.Q.x); |
| 2046 | mpfree(c->sec->ec.Q.a.y); | 2088 | mpfree(c->sec->ec.Q.y); |
| 2047 | mpfree(c->sec->ec.Q.d); | 2089 | mpfree(c->sec->ec.Q.d); |
| 2048 | ecdomfree(&c->sec->ec.dom); | 2090 | ecdomfree(&c->sec->ec.dom); |
| 2049 | 2091 | ||
| @@ -2141,13 +2183,17 @@ setAlgs(TlsConnection *c, int a) · 91 unmodified lines | |||
| 2141 | } | 2183 | } |
| 2142 | 2184 | ||
| 2143 | static int | 2185 | static int |
| 2144 | okCipher(Ints *cv, int ispsk) | 2186 | okCipher(Ints *cv, int ispsk, int canec) |
| 2145 | { | 2187 | { |
| 2146 | int i, c; | 2188 | int i, c; |
| 2147 | 2189 | ||
| 2148 | for(i = 0; i < nelem(cipherAlgs); i++) { | 2190 | for(i = 0; i < nelem(cipherAlgs); i++) { |
| 2149 | c = cipherAlgs[i].tlsid; | 2191 | c = cipherAlgs[i].tlsid; |
| 2150 | if(!cipherAlgs[i].ok || isECDSA(c) || isDHE(c) || isPSK(c) != ispsk) | 2192 | if(!cipherAlgs[i].ok || isECDSA(c) || isDHE(c)) |
| 2193 | continue; | ||
| 2194 | if(isPSK(c) != ispsk) | ||
| 2195 | continue; | ||
| 2196 | if(isECDHE(c) && !canec) | ||
| 2151 | continue; | 2197 | continue; |
| 2152 | if(lookupid(cv, c) >= 0) | 2198 | if(lookupid(cv, c) >= 0) |
| 2153 | return c; | 2199 | return c; |
| @@ -2183,7 +2229,7 @@ initCiphers(void) · 29 unmodified lines | |||
| 2183 | unlock(&ciphLock); | 2229 | unlock(&ciphLock); |
| 2184 | return nciphers; | 2230 | return nciphers; |
| 2185 | } | 2231 | } |
| 2186 | j = open("#a/tls/encalgs", OREAD); | 2232 | j = open("#a/tls/encalgs", OREAD|OCEXEC); |
| 2187 | if(j < 0){ | 2233 | if(j < 0){ |
| 2188 | werrstr("can't open #a/tls/encalgs: %r"); | 2234 | werrstr("can't open #a/tls/encalgs: %r"); |
| 2189 | goto out; | 2235 | goto out; |
| @@ -2207,7 +2253,7 @@ initCiphers(void) · 17 unmodified lines | |||
| 2207 | cipherAlgs[i].ok = ok; | 2253 | cipherAlgs[i].ok = ok; |
| 2208 | } | 2254 | } |
| 2209 | 2255 | ||
| 2210 | j = open("#a/tls/hashalgs", OREAD); | 2256 | j = open("#a/tls/hashalgs", OREAD|OCEXEC); |
| 2211 | if(j < 0){ | 2257 | if(j < 0){ |
| 2212 | werrstr("can't open #a/tls/hashalgs: %r"); | 2258 | werrstr("can't open #a/tls/hashalgs: %r"); |
| 2213 | goto out; | 2259 | goto out; |
| @@ -2266,7 +2312,7 @@ factotum_rsa_open(RSApub *rsapub) · 52 unmodified lines | |||
| 2266 | AuthRpc *rpc; | 2312 | AuthRpc *rpc; |
| 2267 | 2313 | ||
| 2268 | // start talking to factotum | 2314 | // start talking to factotum |
| 2269 | if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) | 2315 | if((afd = open("/mnt/factotum/rpc", ORDWR|OCEXEC)) < 0) |
| 2270 | return nil; | 2316 | return nil; |
| 2271 | if((rpc = auth_allocrpc(afd)) == nil){ | 2317 | if((rpc = auth_allocrpc(afd)) == nil){ |
| 2272 | close(afd); | 2318 | close(afd); |
| @@ -2318,114 +2364,55 @@ factotum_rsa_close(AuthRpc *rpc) · 45 unmodified lines | |||
| 2318 | } | 2364 | } |
| 2319 | 2365 | ||
| 2320 | static void | 2366 | static void |
| 2321 | tlsPmd5(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed0, int nseed0, uchar *seed1, int nseed1) | 2367 | tlsP(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed, int nseed, |
| 2322 | { | 2368 | DigestState* (*x)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*), int xlen) |
| 2323 | uchar ai[MD5dlen], tmp[MD5dlen]; | ||
| 2324 | int i, n; | ||
| 2325 | MD5state *s; | ||
| 2326 | |||
| 2327 | // generate a1 | ||
| 2328 | s = hmac_md5(label, nlabel, key, nkey, nil, nil); | ||
| 2329 | s = hmac_md5(seed0, nseed0, key, nkey, nil, s); | ||
| 2330 | hmac_md5(seed1, nseed1, key, nkey, ai, s); | ||
| 2331 | |||
| 2332 | while(nbuf > 0) { | ||
| 2333 | s = hmac_md5(ai, MD5dlen, key, nkey, nil, nil); | ||
| 2334 | s = hmac_md5(label, nlabel, key, nkey, nil, s); | ||
| 2335 | s = hmac_md5(seed0, nseed0, key, nkey, nil, s); | ||
| 2336 | hmac_md5(seed1, nseed1, key, nkey, tmp, s); | ||
| 2337 | n = MD5dlen; | ||
| 2338 | if(n > nbuf) | ||
| 2339 | n = nbuf; | ||
| 2340 | for(i = 0; i < n; i++) | ||
| 2341 | buf[i] ^= tmp[i]; | ||
| 2342 | buf += n; | ||
| 2343 | nbuf -= n; | ||
| 2344 | hmac_md5(ai, MD5dlen, key, nkey, tmp, nil); | ||
| 2345 | memmove(ai, tmp, MD5dlen); | ||
| 2346 | } | ||
| 2347 | } | ||
| 2348 | |||
| 2349 | static void | ||
| 2350 | tlsPsha1(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed0, int nseed0, uchar *seed1, int nseed1) | ||
| 2351 | { | ||
| 2352 | uchar ai[SHA1dlen], tmp[SHA1dlen]; | ||
| 2353 | int i, n; | ||
| 2354 | SHAstate *s; | ||
| 2355 | |||
| 2356 | // generate a1 | ||
| 2357 | s = hmac_sha1(label, nlabel, key, nkey, nil, nil); | ||
| 2358 | s = hmac_sha1(seed0, nseed0, key, nkey, nil, s); | ||
| 2359 | hmac_sha1(seed1, nseed1, key, nkey, ai, s); | ||
| 2360 | |||
| 2361 | while(nbuf > 0) { | ||
| 2362 | s = hmac_sha1(ai, SHA1dlen, key, nkey, nil, nil); | ||
| 2363 | s = hmac_sha1(label, nlabel, key, nkey, nil, s); | ||
| 2364 | s = hmac_sha1(seed0, nseed0, key, nkey, nil, s); | ||
| 2365 | hmac_sha1(seed1, nseed1, key, nkey, tmp, s); | ||
| 2366 | n = SHA1dlen; | ||
| 2367 | if(n > nbuf) | ||
| 2368 | n = nbuf; | ||
| 2369 | for(i = 0; i < n; i++) | ||
| 2370 | buf[i] ^= tmp[i]; | ||
| 2371 | buf += n; | ||
| 2372 | nbuf -= n; | ||
| 2373 | hmac_sha1(ai, SHA1dlen, key, nkey, tmp, nil); | ||
| 2374 | memmove(ai, tmp, SHA1dlen); | ||
| 2375 | } | ||
| 2376 | } | ||
| 2377 | |||
| 2378 | static void | ||
| 2379 | p_sha256(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed, int nseed) | ||
| 2380 | { | 2369 | { |
| 2381 | uchar ai[SHA2_256dlen], tmp[SHA2_256dlen]; | 2370 | uchar ai[SHA2_256dlen], tmp[SHA2_256dlen]; |
| 2382 | SHAstate *s; | 2371 | DigestState *s; |
| 2383 | int n; | 2372 | int n; |
| 2384 | 2373 | ||
| 2374 | assert(sizeof(ai) <= xlen && sizeof(tmp) <= xlen); | ||
| 2385 | // generate a1 | 2375 | // generate a1 |
| 2386 | s = hmac_sha2_256(label, nlabel, key, nkey, nil, nil); | 2376 | s = x(label, nlabel, key, nkey, nil, nil); |
| 2387 | hmac_sha2_256(seed, nseed, key, nkey, ai, s); | 2377 | x(seed, nseed, key, nkey, ai, s); |
| 2388 | 2378 | ||
| 2389 | while(nbuf > 0) { | 2379 | while(nbuf > 0) { |
| 2390 | s = hmac_sha2_256(ai, SHA2_256dlen, key, nkey, nil, nil); | 2380 | s = x(ai, xlen, key, nkey, nil, nil); |
| 2391 | s = hmac_sha2_256(label, nlabel, key, nkey, nil, s); | 2381 | s = x(label, nlabel, key, nkey, nil, s); |
| 2392 | hmac_sha2_256(seed, nseed, key, nkey, tmp, s); | 2382 | x(seed, nseed, key, nkey, tmp, s); |
| 2393 | n = SHA2_256dlen; | 2383 | n = xlen; |
| 2394 | if(n > nbuf) | 2384 | if(n > nbuf) |
| 2395 | n = nbuf; | 2385 | n = nbuf; |
| 2396 | memmove(buf, tmp, n); | 2386 | memmove(buf, tmp, n); |
| 2397 | buf += n; | 2387 | buf += n; |
| 2398 | nbuf -= n; | 2388 | nbuf -= n; |
| 2399 | hmac_sha2_256(ai, SHA2_256dlen, key, nkey, tmp, nil); | 2389 | x(ai, xlen, key, nkey, tmp, nil); |
| 2400 | memmove(ai, tmp, SHA2_256dlen); | 2390 | memmove(ai, tmp, xlen); |
| 2401 | } | 2391 | } |
| 2402 | } | 2392 | } |
| 2403 | 2393 | ||
| 2404 | // fill buf with md5(args)^sha1(args) | 2394 | // fill buf with md5(args)^sha1(args) |
| 2405 | static void | 2395 | static void |
| 2406 | tls10PRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) | 2396 | tls10PRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed) |
| 2407 | { | 2397 | { |
| 2408 | int nlabel = strlen(label); | 2398 | int nlabel = strlen(label); |
| 2409 | int n = (nkey + 1) >> 1; | 2399 | int n = (nkey + 1) >> 1; |
| 2410 | 2400 | ||
| 2411 | memset(buf, 0, nbuf); | 2401 | tlsP(buf, nbuf, key, n, (uchar*)label, nlabel, seed, nseed, |
| 2412 | tlsPmd5(buf, nbuf, key, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1); | 2402 | hmac_md5, MD5dlen); |
| 2413 | tlsPsha1(buf, nbuf, key+nkey-n, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1); | 2403 | tlsP(buf, nbuf, key+nkey-n, n, (uchar*)label, nlabel, seed, nseed, |
| 2404 | hmac_sha1, SHA1dlen); | ||
| 2414 | } | 2405 | } |
| 2415 | 2406 | ||
| 2416 | static void | 2407 | static void |
| 2417 | tls12PRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) | 2408 | tls12PRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed) |
| 2418 | { | 2409 | { |
| 2419 | uchar seed[2*RandomSize]; | 2410 | tlsP(buf, nbuf, key, nkey, (uchar*)label, strlen(label), seed, nseed, |
| 2420 | 2411 | hmac_sha2_256, SHA2_256dlen); | |
| 2421 | assert(nseed0+nseed1 <= sizeof(seed)); | ||
| 2422 | memmove(seed, seed0, nseed0); | ||
| 2423 | memmove(seed+nseed0, seed1, nseed1); | ||
| 2424 | p_sha256(buf, nbuf, key, nkey, (uchar*)label, strlen(label), seed, nseed0+nseed1); | ||
| 2425 | } | 2412 | } |
| 2426 | 2413 | ||
| 2427 | static void | 2414 | static void |
| 2428 | sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) | 2415 | sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed) |
| 2429 | { | 2416 | { |
| 2430 | uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26]; | 2417 | uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26]; |
| 2431 | DigestState *s; | 2418 | DigestState *s; |
| @@ -2440,8 +2427,7 @@ sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, in · 8 unmodified lines | |||
| 2440 | tmp[i] = 'A' - 1 + len; | 2427 | tmp[i] = 'A' - 1 + len; |
| 2441 | s = sha1(tmp, len, nil, nil); | 2428 | s = sha1(tmp, len, nil, nil); |
| 2442 | s = sha1(key, nkey, nil, s); | 2429 | s = sha1(key, nkey, nil, s); |
| 2443 | s = sha1(seed0, nseed0, nil, s); | 2430 | sha1(seed, nseed, sha1dig, s); |
| 2444 | sha1(seed1, nseed1, sha1dig, s); | ||
| 2445 | s = md5(key, nkey, nil, nil); | 2431 | s = md5(key, nkey, nil, nil); |
| 2446 | md5(sha1dig, SHA1dlen, md5dig, s); | 2432 | md5(sha1dig, SHA1dlen, md5dig, s); |
| 2447 | n = MD5dlen; | 2433 | n = MD5dlen; |
| @@ -2491,18 +2477,18 @@ sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient) · 43 unmodified lines | |||
| 2491 | static void | 2477 | static void |
| 2492 | tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient) | 2478 | tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient) |
| 2493 | { | 2479 | { |
| 2494 | uchar h0[MD5dlen], h1[SHA1dlen]; | 2480 | uchar h[MD5dlen+SHA1dlen]; |
| 2495 | char *label; | 2481 | char *label; |
| 2496 | 2482 | ||
| 2497 | // get current hash value, but allow further messages to be hashed in | 2483 | // get current hash value, but allow further messages to be hashed in |
| 2498 | md5(nil, 0, h0, &hsh.md5); | 2484 | md5(nil, 0, h, &hsh.md5); |
| 2499 | sha1(nil, 0, h1, &hsh.sha1); | 2485 | sha1(nil, 0, h+MD5dlen, &hsh.sha1); |
| 2500 | 2486 | ||
| 2501 | if(isclient) | 2487 | if(isclient) |
| 2502 | label = "client finished"; | 2488 | label = "client finished"; |
| 2503 | else | 2489 | else |
| 2504 | label = "server finished"; | 2490 | label = "server finished"; |
| 2505 | tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen); | 2491 | tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h)); |
| 2506 | } | 2492 | } |
| 2507 | 2493 | ||
| 2508 | static void | 2494 | static void |
| @@ -2518,7 +2504,7 @@ tls12SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient) · 9 unmodified lines | |||
| 2518 | label = "client finished"; | 2504 | label = "client finished"; |
| 2519 | else | 2505 | else |
| 2520 | label = "server finished"; | 2506 | label = "server finished"; |
| 2521 | p_sha256(finished, TLSFinishedLen, sec->sec, MasterSecretSize, (uchar*)label, strlen(label), seed, SHA2_256dlen); | 2507 | tls12PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen); |
| 2522 | } | 2508 | } |
| 2523 | 2509 | ||
| 2524 | static void | 2510 | static void |
| @@ -2528,8 +2514,9 @@ tlsSecInits(TlsSec *sec, int cvers, uchar *crandom) · 3 unmodified lines | |||
| 2528 | sec->clientVers = cvers; | 2514 | sec->clientVers = cvers; |
| 2529 | memmove(sec->crandom, crandom, RandomSize); | 2515 | memmove(sec->crandom, crandom, RandomSize); |
| 2530 | 2516 | ||
| 2531 | put32(sec->srandom, time(nil)); | 2517 | // putting time()'s output to the first 4 bytes is no |
| 2532 | genrandom(sec->srandom+4, RandomSize-4); | 2518 | // longer recommended and is not useful |
| 2519 | genrandom(sec->srandom, RandomSize); | ||
| 2533 | } | 2520 | } |
| 2534 | 2521 | ||
| 2535 | static int | 2522 | static int |
| @@ -2554,61 +2541,88 @@ tlsSecRSAs(TlsSec *sec, Bytes *epm) · 18 unmodified lines | |||
| 2554 | } | 2541 | } |
| 2555 | 2542 | ||
| 2556 | static Bytes* | 2543 | static Bytes* |
| 2557 | tlsSecECDHEs1(TlsSec *sec, Namedcurve *nc) | 2544 | tlsSecECDHEs1(TlsSec *sec) |
| 2558 | { | 2545 | { |
| 2559 | ECdomain *dom = &sec->ec.dom; | 2546 | ECdomain *dom = &sec->ec.dom; |
| 2560 | ECpriv *Q = &sec->ec.Q; | 2547 | ECpriv *Q = &sec->ec.Q; |
| 2561 | Bytes *par; | 2548 | Bytes *par; |
| 2562 | int n; | 2549 | int n; |
| 2563 | 2550 | ||
| 2564 | ecdominit(dom, nc->init); | 2551 | if(sec->nc == nil) |
| 2565 | memset(Q, 0, sizeof(*Q)); | 2552 | return nil; |
| 2566 | Q->a.x = mpnew(0); | 2553 | if(sec->nc->tlsid == X25519){ |
| 2567 | Q->a.y = mpnew(0); | 2554 | par = newbytes(1+2+1+32); |
| 2568 | Q->d = mpnew(0); | 2555 | par->data[0] = 3; |
| 2569 | ecgen(dom, Q); | 2556 | put16(par->data+1, X25519); |
| 2570 | n = 1 + 2*((mpsignif(dom->p)+7)/8); | 2557 | par->data[3] = 32; |
| 2571 | par = newbytes(1+2+1+n); | 2558 | curve25519_dh_new(sec->X, par->data+4); |
| 2572 | par->data[0] = 3; | 2559 | }else{ |
| 2573 | put16(par->data+1, nc->tlsid); | 2560 | ecdominit(dom, sec->nc->init); |
| 2574 | n = ecencodepub(dom, (ECpub*)Q, par->data+4, par->len-4); | 2561 | memset(Q, 0, sizeof(*Q)); |
| 2575 | par->data[3] = n; | 2562 | Q->x = mpnew(0); |
| 2576 | par->len = 1+2+1+n; | 2563 | Q->y = mpnew(0); |
| 2577 | 2564 | Q->d = mpnew(0); | |
| 2565 | ecgen(dom, Q); | ||
| 2566 | n = 1 + 2*((mpsignif(dom->p)+7)/8); | ||
| 2567 | par = newbytes(1+2+1+n); | ||
| 2568 | par->data[0] = 3; | ||
| 2569 | put16(par->data+1, sec->nc->tlsid); | ||
| 2570 | n = ecencodepub(dom, Q, par->data+4, par->len-4); | ||
| 2571 | par->data[3] = n; | ||
| 2572 | par->len = 1+2+1+n; | ||
| 2573 | } | ||
| 2578 | return par; | 2574 | return par; |
| 2579 | } | 2575 | } |
| 2580 | 2576 | ||
| 2581 | static int | 2577 | static int |
| 2582 | tlsSecECDHEs2(TlsSec *sec, Bytes *Yc) | 2578 | tlsSecECDHEs2(TlsSec *sec, Bytes *Yc) |
| 2583 | { | 2579 | { |
| 2580 | static char zero[32] = {0}; | ||
| 2584 | ECdomain *dom = &sec->ec.dom; | 2581 | ECdomain *dom = &sec->ec.dom; |
| 2585 | ECpriv *Q = &sec->ec.Q; | 2582 | ECpriv *Q = &sec->ec.Q; |
| 2586 | ECpoint K; | 2583 | ECpoint K; |
| 2587 | ECpub *Y; | 2584 | ECpub *Y; |
| 2585 | Bytes *Z; | ||
| 2588 | 2586 | ||
| 2589 | if(Yc == nil){ | 2587 | if(Yc == nil){ |
| 2590 | werrstr("no public key"); | 2588 | werrstr("no public key"); |
| 2591 | return -1; | 2589 | return -1; |
| 2592 | } | 2590 | } |
| 2593 | 2591 | ||
| 2594 | if((Y = ecdecodepub(dom, Yc->data, Yc->len)) == nil){ | 2592 | if(sec->nc->tlsid == X25519){ |
| 2595 | werrstr("bad public key"); | 2593 | if(Yc->len != 32){ |
| 2596 | return -1; | 2594 | werrstr("bad public key"); |
| 2597 | } | 2595 | return -1; |
| 2598 | 2596 | } | |
| 2599 | memset(&K, 0, sizeof(K)); | 2597 | Z = newbytes(32); |
| 2600 | K.x = mpnew(0); | 2598 | curve25519_dh_finish(sec->X, Yc->data, Z->data); |
| 2601 | K.y = mpnew(0); | 2599 | // rfc wants us to terminate the connection if |
| 2600 | // shared secret == all zeroes. | ||
| 2601 | if(tsmemcmp(Z->data, zero, Z->len) == 0){ | ||
| 2602 | werrstr("unlucky shared key"); | ||
| 2603 | freebytes(Z); | ||
| 2604 | return -1; | ||
| 2605 | } | ||
| 2606 | setMasterSecret(sec, Z); | ||
| 2607 | }else{ | ||
| 2608 | if((Y = ecdecodepub(dom, Yc->data, Yc->len)) == nil){ | ||
| 2609 | werrstr("bad public key"); | ||
| 2610 | return -1; | ||
| 2611 | } | ||
| 2602 | 2612 | ||
| 2603 | ecmul(dom, Y, Q->d, &K); | 2613 | memset(&K, 0, sizeof(K)); |
| 2614 | K.x = mpnew(0); | ||
| 2615 | K.y = mpnew(0); | ||
| 2604 | 2616 | ||
| 2605 | setMasterSecret(sec, mptobytes(K.x, (mpsignif(dom->p)+7)/8)); | 2617 | ecmul(dom, Y, Q->d, &K); |
| 2606 | 2618 | ||
| 2607 | mpfree(K.x); | 2619 | setMasterSecret(sec, mptobytes(K.x, (mpsignif(dom->p)+7)/8)); |
| 2608 | mpfree(K.y); | ||
| 2609 | 2620 | ||
| 2610 | ecpubfree(Y); | 2621 | mpfree(K.x); |
| 2622 | mpfree(K.y); | ||
| 2611 | 2623 | ||
| 2624 | ecpubfree(Y); | ||
| 2625 | } | ||
| 2612 | return 0; | 2626 | return 0; |
| 2613 | } | 2627 | } |
| 2614 | 2628 | ||
| @@ -2617,8 +2631,8 @@ tlsSecInitc(TlsSec *sec, int cvers) · 2 unmodified lines | |||
| 2617 | { | 2631 | { |
| 2618 | memset(sec, 0, sizeof(*sec)); | 2632 | memset(sec, 0, sizeof(*sec)); |
| 2619 | sec->clientVers = cvers; | 2633 | sec->clientVers = cvers; |
| 2620 | put32(sec->crandom, time(nil)); | 2634 | // see the comment on tlsSecInits |
| 2621 | genrandom(sec->crandom+4, RandomSize-4); | 2635 | genrandom(sec->crandom, RandomSize); |
| 2622 | } | 2636 | } |
| 2623 | 2637 | ||
| 2624 | static Bytes* | 2638 | static Bytes* |
| @@ -2676,13 +2690,15 @@ tlsSecVers(TlsSec *sec, int v) · 51 unmodified lines | |||
| 2676 | static int | 2690 | static int |
| 2677 | setSecrets(TlsConnection *c, int isclient) | 2691 | setSecrets(TlsConnection *c, int isclient) |
| 2678 | { | 2692 | { |
| 2679 | uchar kd[MaxKeyData]; | 2693 | uchar kd[MaxKeyData], seed[2*RandomSize]; |
| 2680 | char *secrets; | 2694 | char *secrets; |
| 2681 | int rv; | 2695 | int rv; |
| 2682 | 2696 | ||
| 2683 | assert(c->nsecret <= sizeof(kd)); | 2697 | assert(c->nsecret <= sizeof(kd)); |
| 2684 | secrets = emalloc(2*c->nsecret); | 2698 | secrets = emalloc(2*c->nsecret); |
| 2685 | 2699 | ||
| 2700 | memmove(seed, c->sec->srandom, RandomSize); | ||
| 2701 | memmove(seed+RandomSize, c->sec->crandom, RandomSize); | ||
| 2686 | /* | 2702 | /* |
| 2687 | * generate secret keys from the master secret. | 2703 | * generate secret keys from the master secret. |
| 2688 | * | 2704 | * |
| @@ -2691,7 +2707,7 @@ setSecrets(TlsConnection *c, int isclient) · 2 unmodified lines | |||
| 2691 | * but it's all generated using the same function. | 2707 | * but it's all generated using the same function. |
| 2692 | */ | 2708 | */ |
| 2693 | (*c->sec->prf)(kd, c->nsecret, c->sec->sec, MasterSecretSize, "key expansion", | 2709 | (*c->sec->prf)(kd, c->nsecret, c->sec->sec, MasterSecretSize, "key expansion", |
| 2694 | c->sec->srandom, RandomSize, c->sec->crandom, RandomSize); | 2710 | seed, sizeof(seed)); |
| 2695 | 2711 | ||
| 2696 | enc64(secrets, 2*c->nsecret, kd, c->nsecret); | 2712 | enc64(secrets, 2*c->nsecret, kd, c->nsecret); |
| 2697 | memset(kd, 0, c->nsecret); | 2713 | memset(kd, 0, c->nsecret); |
| @@ -2710,6 +2726,8 @@ setSecrets(TlsConnection *c, int isclient) · 12 unmodified lines | |||
| 2710 | static void | 2726 | static void |
| 2711 | setMasterSecret(TlsSec *sec, Bytes *pm) | 2727 | setMasterSecret(TlsSec *sec, Bytes *pm) |
| 2712 | { | 2728 | { |
| 2729 | uchar seed[2*RandomSize]; | ||
| 2730 | |||
| 2713 | if(sec->psklen > 0){ | 2731 | if(sec->psklen > 0){ |
| 2714 | Bytes *opm = pm; | 2732 | Bytes *opm = pm; |
| 2715 | uchar *p; | 2733 | uchar *p; |
| @@ -2726,8 +2744,10 @@ setMasterSecret(TlsSec *sec, Bytes *pm) · 10 unmodified lines | |||
| 2726 | freebytes(opm); | 2744 | freebytes(opm); |
| 2727 | } | 2745 | } |
| 2728 | 2746 | ||
| 2747 | memmove(seed, sec->crandom, RandomSize); | ||
| 2748 | memmove(seed+RandomSize, sec->srandom, RandomSize); | ||
| 2729 | (*sec->prf)(sec->sec, MasterSecretSize, pm->data, pm->len, "master secret", | 2749 | (*sec->prf)(sec->sec, MasterSecretSize, pm->data, pm->len, "master secret", |
| 2730 | sec->crandom, RandomSize, sec->srandom, RandomSize); | 2750 | seed, sizeof(seed)); |
| 2731 | 2751 | ||
| 2732 | memset(pm->data, 0, pm->len); | 2752 | memset(pm->data, 0, pm->len); |
| 2733 | freebytes(pm); | 2753 | freebytes(pm); |