@@ -355,3 +355,221 @@ func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHel
355
355
356
356
return ka .preMasterSecret , ka .ckx , nil
357
357
}
358
+
359
+ // ecdhePskKeyAgreement implements a TLS key agreement where the server
360
+ // generates an ephemeral EC public/private key pair and signs it. The
361
+ // pre-master secret is then calculated using ECDH with Pre-shared key.
362
+ type ecdhePskKeyAgreement struct {
363
+ version uint16
364
+ params ecdheParameters
365
+
366
+ // ckx and otherSecret are generated in processServerKeyExchange
367
+ // and returned in generateClientKeyExchange.
368
+ ckx * clientKeyExchangeMsg
369
+ otherSecret []byte
370
+ pskIdentity string
371
+ }
372
+
373
+ func (ka * ecdhePskKeyAgreement ) generateServerKeyExchange (config * Config , cert * Certificate , clientHello * clientHelloMsg , hello * serverHelloMsg ) (* serverKeyExchangeMsg , error ) {
374
+ var curveID CurveID
375
+ for _ , c := range clientHello .supportedCurves {
376
+ if config .supportsCurve (c ) {
377
+ curveID = c
378
+ break
379
+ }
380
+ }
381
+
382
+ if curveID == 0 {
383
+ return nil , errors .New ("tls: no supported elliptic curves offered" )
384
+ }
385
+ if _ , ok := curveForCurveID (curveID ); curveID != X25519 && ! ok {
386
+ return nil , errors .New ("tls: CurvePreferences includes unsupported curve" )
387
+ }
388
+
389
+ params , err := generateECDHEParameters (config .rand (), curveID )
390
+ if err != nil {
391
+ return nil , err
392
+ }
393
+ ka .params = params
394
+
395
+ ecdhePublic := params .PublicKey ()
396
+
397
+ serverECDHEParamsSize := 1 + 2 + 1 + len (ecdhePublic )
398
+ skx := new (serverKeyExchangeMsg )
399
+ skx .key = make ([]byte , 2 + serverECDHEParamsSize )
400
+
401
+ // See RFC 4492, Section 5.4.
402
+ serverECDHEParams := skx .key [2 :]
403
+ serverECDHEParams [0 ] = 3 // named curve
404
+ serverECDHEParams [1 ] = byte (curveID >> 8 )
405
+ serverECDHEParams [2 ] = byte (curveID )
406
+ serverECDHEParams [3 ] = byte (len (ecdhePublic ))
407
+ copy (serverECDHEParams [4 :], ecdhePublic )
408
+
409
+ return skx , nil
410
+ }
411
+
412
+ func (ka * ecdhePskKeyAgreement ) processClientKeyExchange (config * Config , cert * Certificate , ckx * clientKeyExchangeMsg , version uint16 ) ([]byte , error ) {
413
+ pskConfig , ok := config .Extra .(PSKConfig )
414
+ if ! ok {
415
+ return nil , errors .New ("bad Config - Extra not of type PSKConfig" )
416
+ }
417
+
418
+ if pskConfig .GetKey == nil {
419
+ return nil , errors .New ("bad Config - GetKey required for PSK" )
420
+ }
421
+
422
+ if len (ckx .ciphertext ) < 2 {
423
+ return nil , errors .New ("bad ClientKeyExchange" )
424
+ }
425
+
426
+ ciphertext := ckx .ciphertext
427
+ pskIdentityLen := int (ciphertext [0 ])<< 8 | int (ciphertext [1 ])
428
+ if len (ciphertext ) < (pskIdentityLen + 2 ) {
429
+ return nil , errors .New ("bad ClientKeyExchange" )
430
+ }
431
+ pskIdentity := string (ciphertext [2 : 2 + pskIdentityLen ])
432
+ ciphertext = ciphertext [2 + pskIdentityLen :]
433
+
434
+ // ciphertext is actually the pskIdentity here
435
+ psk , err := pskConfig .GetKey (pskIdentity )
436
+ if err != nil {
437
+ return nil , err
438
+ }
439
+ pskLen := len (psk )
440
+
441
+ if len (ciphertext ) < 1 {
442
+ return nil , errors .New ("bad ClientKeyExchange" )
443
+ }
444
+
445
+ publicKeyLen := int (ciphertext [0 ])
446
+ if len (ciphertext ) < (publicKeyLen + 1 ) {
447
+ return nil , errors .New ("bad ClientKeyExchange" )
448
+ }
449
+ publicKey := ciphertext [1 : 1 + publicKeyLen ]
450
+
451
+ otherSecret := ka .params .SharedKey (publicKey )
452
+ if otherSecret == nil {
453
+ return nil , errClientKeyExchange
454
+ }
455
+ otherSecretLen := len (otherSecret )
456
+
457
+ preMasterSecret := make ([]byte , 4 + pskLen + otherSecretLen )
458
+ preMasterSecret [0 ] = byte (otherSecretLen >> 8 )
459
+ preMasterSecret [1 ] = byte (otherSecretLen )
460
+ copy (preMasterSecret [2 :], otherSecret )
461
+ preMasterSecret [2 + otherSecretLen ] = byte (pskLen >> 8 )
462
+ preMasterSecret [3 + otherSecretLen ] = byte (pskLen )
463
+ copy (preMasterSecret [4 + otherSecretLen :], psk )
464
+
465
+ return preMasterSecret , nil
466
+ }
467
+
468
+ func (ka * ecdhePskKeyAgreement ) processServerKeyExchange (config * Config , clientHello * clientHelloMsg , serverHello * serverHelloMsg , cert * x509.Certificate , skx * serverKeyExchangeMsg ) error {
469
+ pskConfig , ok := config .Extra .(PSKConfig )
470
+ if ! ok {
471
+ return errors .New ("bad Config - Extra not of type PSKConfig" )
472
+ }
473
+
474
+ if pskConfig .GetIdentity == nil {
475
+ return errors .New ("bad PSKConfig - GetIdentity required for PSK" )
476
+ }
477
+
478
+ if pskConfig .GetKey == nil {
479
+ return errors .New ("bad Config - GetKey required for PSK" )
480
+ }
481
+
482
+ key := skx .key
483
+
484
+ if len (key ) < 2 {
485
+ return errServerKeyExchange
486
+ }
487
+ pskIdentityFromServerLen := int (key [0 ])<< 8 | int (key [1 ])
488
+ if pskIdentityFromServerLen > 0 {
489
+ if len (key ) < (pskIdentityFromServerLen + 2 ) {
490
+ return errServerKeyExchange
491
+ }
492
+ pskIdentityFromServer := string (key [2 : 2 + pskIdentityFromServerLen ])
493
+ key = key [2 + pskIdentityFromServerLen :]
494
+ _ = pskIdentityFromServer
495
+ }
496
+
497
+ pskIdentity := pskConfig .GetIdentity ()
498
+ bPskIdentity := []byte (pskIdentity )
499
+ pskIdentityLen := len (bPskIdentity )
500
+ ka .pskIdentity = pskIdentity
501
+
502
+ if len (key ) < 3 {
503
+ return errServerKeyExchange
504
+ }
505
+
506
+ if key [0 ] != 3 { // named curve
507
+ return errors .New ("tls: server selected unsupported curve" )
508
+ }
509
+ curveID := CurveID (key [1 ])<< 8 | CurveID (key [2 ])
510
+
511
+ publicLen := int (key [3 ])
512
+ if publicLen + 4 > len (key ) {
513
+ return errServerKeyExchange
514
+ }
515
+ serverECDHEParams := key [:4 + publicLen ]
516
+ publicKey := serverECDHEParams [4 :]
517
+
518
+ if _ , ok := curveForCurveID (curveID ); curveID != X25519 && ! ok {
519
+ return errors .New ("tls: server selected unsupported curve" )
520
+ }
521
+
522
+ params , err := generateECDHEParameters (config .rand (), curveID )
523
+ if err != nil {
524
+ return err
525
+ }
526
+ ka .params = params
527
+
528
+ ka .otherSecret = params .SharedKey (publicKey )
529
+ if ka .otherSecret == nil {
530
+ return errServerKeyExchange
531
+ }
532
+
533
+ ourPublicKey := params .PublicKey ()
534
+ ka .ckx = new (clientKeyExchangeMsg )
535
+ ka .ckx .ciphertext = make ([]byte , 2 + pskIdentityLen + 1 + len (ourPublicKey ))
536
+ ka .ckx .ciphertext [0 ] = byte (pskIdentityLen >> 8 )
537
+ ka .ckx .ciphertext [1 ] = byte (pskIdentityLen )
538
+ copy (ka .ckx .ciphertext [2 :], bPskIdentity )
539
+ ka .ckx .ciphertext [2 + pskIdentityLen ] = byte (len (ourPublicKey ))
540
+ copy (ka .ckx .ciphertext [3 + pskIdentityLen :], ourPublicKey )
541
+
542
+ return nil
543
+ }
544
+
545
+ func (ka * ecdhePskKeyAgreement ) generateClientKeyExchange (config * Config , clientHello * clientHelloMsg , cert * x509.Certificate ) ([]byte , * clientKeyExchangeMsg , error ) {
546
+ pskConfig , ok := config .Extra .(PSKConfig )
547
+ if ! ok {
548
+ return nil , nil , errors .New ("bad Config - Extra not of type PSKConfig" )
549
+ }
550
+
551
+ if pskConfig .GetKey == nil {
552
+ return nil , nil , errors .New ("bad Config - GetKey required for PSK" )
553
+ }
554
+
555
+ if ka .ckx == nil {
556
+ return nil , nil , errors .New ("tls: missing ServerKeyExchange message" )
557
+ }
558
+
559
+ psk , err := pskConfig .GetKey (ka .pskIdentity )
560
+ if err != nil {
561
+ return nil , nil , err
562
+ }
563
+ pskLen := len (psk )
564
+
565
+ otherSecretLen := len (ka .otherSecret )
566
+ preMasterSecret := make ([]byte , 4 + pskLen + otherSecretLen )
567
+ preMasterSecret [0 ] = byte (otherSecretLen >> 8 )
568
+ preMasterSecret [1 ] = byte (otherSecretLen )
569
+ copy (preMasterSecret [2 :], ka .otherSecret )
570
+ preMasterSecret [2 + otherSecretLen ] = byte (pskLen >> 8 )
571
+ preMasterSecret [3 + otherSecretLen ] = byte (pskLen )
572
+ copy (preMasterSecret [4 + otherSecretLen :], psk )
573
+
574
+ return preMasterSecret , ka .ckx , nil
575
+ }
0 commit comments