...

Source file src/crypto/tls/key_schedule_test.go

Documentation: crypto/tls

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tls
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/internal/mlkem768"
    10  	"encoding/hex"
    11  	"hash"
    12  	"strings"
    13  	"testing"
    14  	"unicode"
    15  )
    16  
    17  // This file contains tests derived from draft-ietf-tls-tls13-vectors-07.
    18  
    19  func parseVector(v string) []byte {
    20  	v = strings.Map(func(c rune) rune {
    21  		if unicode.IsSpace(c) {
    22  			return -1
    23  		}
    24  		return c
    25  	}, v)
    26  	parts := strings.Split(v, ":")
    27  	v = parts[len(parts)-1]
    28  	res, err := hex.DecodeString(v)
    29  	if err != nil {
    30  		panic(err)
    31  	}
    32  	return res
    33  }
    34  
    35  func TestDeriveSecret(t *testing.T) {
    36  	chTranscript := cipherSuitesTLS13[0].hash.New()
    37  	chTranscript.Write(parseVector(`
    38  	payload (512 octets):  01 00 01 fc 03 03 1b c3 ce b6 bb e3 9c ff
    39  	93 83 55 b5 a5 0a db 6d b2 1b 7a 6a f6 49 d7 b4 bc 41 9d 78 76
    40  	48 7d 95 00 00 06 13 01 13 03 13 02 01 00 01 cd 00 00 00 0b 00
    41  	09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 14 00 12
    42  	00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 33 00
    43  	26 00 24 00 1d 00 20 e4 ff b6 8a c0 5f 8d 96 c9 9d a2 66 98 34
    44  	6c 6b e1 64 82 ba dd da fe 05 1a 66 b4 f1 8d 66 8f 0b 00 2a 00
    45  	00 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03 02
    46  	03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05 02 06 02
    47  	02 02 00 2d 00 02 01 01 00 1c 00 02 40 01 00 15 00 57 00 00 00
    48  	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    49  	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    50  	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    51  	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    52  	00 29 00 dd 00 b8 00 b2 2c 03 5d 82 93 59 ee 5f f7 af 4e c9 00
    53  	00 00 00 26 2a 64 94 dc 48 6d 2c 8a 34 cb 33 fa 90 bf 1b 00 70
    54  	ad 3c 49 88 83 c9 36 7c 09 a2 be 78 5a bc 55 cd 22 60 97 a3 a9
    55  	82 11 72 83 f8 2a 03 a1 43 ef d3 ff 5d d3 6d 64 e8 61 be 7f d6
    56  	1d 28 27 db 27 9c ce 14 50 77 d4 54 a3 66 4d 4e 6d a4 d2 9e e0
    57  	37 25 a6 a4 da fc d0 fc 67 d2 ae a7 05 29 51 3e 3d a2 67 7f a5
    58  	90 6c 5b 3f 7d 8f 92 f2 28 bd a4 0d da 72 14 70 f9 fb f2 97 b5
    59  	ae a6 17 64 6f ac 5c 03 27 2e 97 07 27 c6 21 a7 91 41 ef 5f 7d
    60  	e6 50 5e 5b fb c3 88 e9 33 43 69 40 93 93 4a e4 d3 57 fa d6 aa
    61  	cb 00 21 20 3a dd 4f b2 d8 fd f8 22 a0 ca 3c f7 67 8e f5 e8 8d
    62  	ae 99 01 41 c5 92 4d 57 bb 6f a3 1b 9e 5f 9d`))
    63  
    64  	type args struct {
    65  		secret     []byte
    66  		label      string
    67  		transcript hash.Hash
    68  	}
    69  	tests := []struct {
    70  		name string
    71  		args args
    72  		want []byte
    73  	}{
    74  		{
    75  			`derive secret for handshake "tls13 derived"`,
    76  			args{
    77  				parseVector(`PRK (32 octets):  33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c e2
    78  				10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a`),
    79  				"derived",
    80  				nil,
    81  			},
    82  			parseVector(`expanded (32 octets):  6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba
    83  			b6 97 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba`),
    84  		},
    85  		{
    86  			`derive secret "tls13 c e traffic"`,
    87  			args{
    88  				parseVector(`PRK (32 octets):  9b 21 88 e9 b2 fc 6d 64 d7 1d c3 29 90 0e 20 bb
    89  				41 91 50 00 f6 78 aa 83 9c bb 79 7c b7 d8 33 2c`),
    90  				"c e traffic",
    91  				chTranscript,
    92  			},
    93  			parseVector(`expanded (32 octets):  3f bb e6 a6 0d eb 66 c3 0a 32 79 5a ba 0e
    94  			ff 7e aa 10 10 55 86 e7 be 5c 09 67 8d 63 b6 ca ab 62`),
    95  		},
    96  	}
    97  	for _, tt := range tests {
    98  		t.Run(tt.name, func(t *testing.T) {
    99  			c := cipherSuitesTLS13[0]
   100  			if got := c.deriveSecret(tt.args.secret, tt.args.label, tt.args.transcript); !bytes.Equal(got, tt.want) {
   101  				t.Errorf("cipherSuiteTLS13.deriveSecret() = % x, want % x", got, tt.want)
   102  			}
   103  		})
   104  	}
   105  }
   106  
   107  func TestTrafficKey(t *testing.T) {
   108  	trafficSecret := parseVector(
   109  		`PRK (32 octets):  b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4
   110  		e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38`)
   111  	wantKey := parseVector(
   112  		`key expanded (16 octets):  3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e
   113  		e4 03 bc`)
   114  	wantIV := parseVector(
   115  		`iv expanded (12 octets):  5d 31 3e b2 67 12 76 ee 13 00 0b 30`)
   116  
   117  	c := cipherSuitesTLS13[0]
   118  	gotKey, gotIV := c.trafficKey(trafficSecret)
   119  	if !bytes.Equal(gotKey, wantKey) {
   120  		t.Errorf("cipherSuiteTLS13.trafficKey() gotKey = % x, want % x", gotKey, wantKey)
   121  	}
   122  	if !bytes.Equal(gotIV, wantIV) {
   123  		t.Errorf("cipherSuiteTLS13.trafficKey() gotIV = % x, want % x", gotIV, wantIV)
   124  	}
   125  }
   126  
   127  func TestExtract(t *testing.T) {
   128  	type args struct {
   129  		newSecret     []byte
   130  		currentSecret []byte
   131  	}
   132  	tests := []struct {
   133  		name string
   134  		args args
   135  		want []byte
   136  	}{
   137  		{
   138  			`extract secret "early"`,
   139  			args{
   140  				nil,
   141  				nil,
   142  			},
   143  			parseVector(`secret (32 octets):  33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c
   144  			e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a`),
   145  		},
   146  		{
   147  			`extract secret "master"`,
   148  			args{
   149  				nil,
   150  				parseVector(`salt (32 octets):  43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25 90 b5
   151  				31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4`),
   152  			},
   153  			parseVector(`secret (32 octets):  18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a
   154  			47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19`),
   155  		},
   156  		{
   157  			`extract secret "handshake"`,
   158  			args{
   159  				parseVector(`IKM (32 octets):  8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d
   160  				35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d`),
   161  				parseVector(`salt (32 octets):  6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba b6 97
   162  				16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba`),
   163  			},
   164  			parseVector(`secret (32 octets):  1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b
   165  			01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac`),
   166  		},
   167  	}
   168  	for _, tt := range tests {
   169  		t.Run(tt.name, func(t *testing.T) {
   170  			c := cipherSuitesTLS13[0]
   171  			if got := c.extract(tt.args.newSecret, tt.args.currentSecret); !bytes.Equal(got, tt.want) {
   172  				t.Errorf("cipherSuiteTLS13.extract() = % x, want % x", got, tt.want)
   173  			}
   174  		})
   175  	}
   176  }
   177  
   178  func TestKyberDecapsulate(t *testing.T) {
   179  	// From https://pq-crystals.org/kyber/data/kyber-submission-nist-round3.zip
   180  	dkBytes, _ := hex.DecodeString("07638FB69868F3D320E5862BD96933FEB311B362093C9B5D50170BCED43F1B536D9A204BB1F22695950BA1F2A9E8EB828B284488760B3FC84FABA04275D5628E39C5B2471374283C503299C0AB49B66B8BBB56A4186624F919A2BA59BB08D8551880C2BEFC4F87F25F59AB587A79C327D792D54C974A69262FF8A78938289E9A87B688B083E0595FE218B6BB1505941CE2E81A5A64C5AAC60417256985349EE47A52420A5F97477B7236AC76BC70E8288729287EE3E34A3DBC3683C0B7B10029FC203418537E7466BA6385A8FF301EE12708F82AAA1E380FC7A88F8F205AB7E88D7E95952A55BA20D09B79A47141D62BF6EB7DD307B08ECA13A5BC5F6B68581C6865B27BBCDDAB142F4B2CBFF488C8A22705FAA98A2B9EEA3530C76662335CC7EA3A00777725EBCCCD2A4636B2D9122FF3AB77123CE0883C1911115E50C9E8A94194E48DD0D09CFFB3ADCD2C1E92430903D07ADBF00532031575AA7F9E7B5A1F3362DEC936D4043C05F2476C07578BC9CBAF2AB4E382727AD41686A96B2548820BB03B32F11B2811AD62F489E951632ABA0D1DF89680CC8A8B53B481D92A68D70B4EA1C3A6A561C0692882B5CA8CC942A8D495AFCB06DE89498FB935B775908FE7A03E324D54CC19D4E1AABD3593B38B19EE1388FE492B43127E5A504253786A0D69AD32601C28E2C88504A5BA599706023A61363E17C6B9BB59BDC697452CD059451983D738CA3FD034E3F5988854CA05031DB09611498988197C6B30D258DFE26265541C89A4B31D6864E9389B03CB74F7EC4323FB9421A4B9790A26D17B0398A26767350909F84D57B6694DF830664CA8B3C3C03ED2AE67B89006868A68527CCD666459AB7F056671000C6164D3A7F266A14D97CBD7004D6C92CACA770B844A4FA9B182E7B18CA885082AC5646FCB4A14E1685FEB0C9CE3372AB95365C04FD83084F80A23FF10A05BF15F7FA5ACC6C0CB462C33CA524FA6B8BB359043BA68609EAA2536E81D08463B19653B5435BA946C9ADDEB202B04B031CC960DCC12E4518D428B32B257A4FC7313D3A7980D80082E934F9D95C32B0A0191A23604384DD9E079BBBAA266D14C3F756B9F2133107433A4E83FA7187282A809203A4FAF841851833D121AC383843A5E55BC2381425E16C7DB4CC9AB5C1B0D91A47E2B8DE0E582C86B6B0D907BB360B97F40AB5D038F6B75C814B27D9B968D419832BC8C2BEE605EF6E5059D33100D90485D378450014221736C07407CAC260408AA64926619788B8601C2A752D1A6CBF820D7C7A04716203225B3895B9342D147A8185CFC1BB65BA06B4142339903C0AC4651385B45D98A8B19D28CD6BAB088787F7EE1B12461766B43CBCCB96434427D93C065550688F6948ED1B5475A425F1B85209D061C08B56C1CC069F6C0A7C6F29358CAB911087732A649D27C9B98F9A48879387D9B00C25959A71654D6F6A946164513E47A75D005986C2363C09F6B537ECA78B9303A5FA457608A586A653A347DB04DFCC19175B3A301172536062A658A95277570C8852CA8973F4AE123A334047DD711C8927A634A03388A527B034BF7A8170FA702C1F7C23EC32D18A2374890BE9C787A9409C82D192C4BB705A2F996CE405DA72C2D9C843EE9F8313ECC7F86D6294D59159D9A879A542E260922ADF999051CC45200C9FFDB60449C49465979272367C083A7D6267A3ED7A7FD47957C219327F7CA73A4007E1627F00B11CC80573C15AEE6640FB8562DFA6B240CA0AD351AC4AC155B96C14C8AB13DD262CDFD51C4BB5572FD616553D17BDD430ACBEA3E95F0B698D66990AB51E5D03783A8B3D278A5720454CF9695CFDCA08485BA099C51CD92A7EA7587C1D15C28E609A81852601B0604010679AA482D51261EC36E36B8719676217FD74C54786488F4B4969C05A8BA27CA3A77CCE73B965923CA554E422B9B61F4754641608AC16C9B8587A32C1C5DD788F88B36B717A46965635DEB67F45B129B99070909C93EB80B42C2B3F3F70343A7CF37E8520E7BCFC416ACA4F18C7981262BA2BFC756AE03278F0EC66DC2057696824BA6769865A601D7148EF6F54E5AF5686AA2906F994CE38A5E0B938F239007003022C03392DF3401B1E4A3A7EBC6161449F73374C8B0140369343D9295FDF511845C4A46EBAAB6CA5492F6800B98C0CC803653A4B1D6E6AAED1932BACC5FEFAA818BA502859BA5494C5F5402C8536A9C4C1888150617F80098F6B2A99C39BC5DC7CF3B5900A21329AB59053ABAA64ED163E859A8B3B3CA3359B750CCC3E710C7AC43C8191CB5D68870C06391C0CB8AEC72B897AC6BE7FBAACC676ED66314C83630E89448C88A1DF04ACEB23ABF2E409EF333C622289C18A2134E650C45257E47475FA33AA537A5A8F7680214716C50D470E3284963CA64F54677AEC54B5272162BF52BC8142E1D4183FC017454A6B5A496831759064024745978CBD51A6CEDC8955DE4CC6D363670A47466E82BE5C23603A17BF22ACDB7CC984AF08C87E14E27753CF587A8EC3447E62C649E887A67C36C9CE98721B697213275646B194F36758673A8ED11284455AFC7A8529F69C97A3C2D7B8C636C0BA55614B768E624E712930F776169B01715725351BC74B47395ED52B25A1313C95164814C34C979CBDFAB85954662CAB485E75087A98CC74BB82CA2D1B5BF2803238480638C40E90B43C7460E7AA917F010151FAB1169987B372ABB59271F7006C24E60236B84B9DDD600623704254617FB498D89E58B0368BCB2103E79353EB587860C1422E476162E425BC2381DB82C6592737E1DD602864B0167A71EC1F223305C02FE25052AF2B3B5A55A0D7A2022D9A798DC0C5874A98702AAF4054C5D80338A5248B5B7BD09C53B5E2A084B047D277A861B1A73BB51488DE04EF573C85230A0470B73175C9FA50594F66A5F50B4150054C93B68186F8B5CBC49316C8548A642B2B36A1D454C7489AC33B2D2CE6668096782A2C1E0866D21A65E16B585E7AF8618BDF3184C1986878508917277B93E10706B1614972B2A94C7310FE9C708C231A1A8AC8D9314A529A97F469BF64962D820648443099A076D55D4CEA824A58304844F99497C10A25148618A315D72CA857D1B04D575B94F85C01D19BEF211BF0AA3362E7041FD16596D808E867B44C4C00D1CDA3418967717F147D0EB21B42AAEE74AC35D0B92414B958531AADF463EC6305AE5ECAF79174002F26DDECC813BF32672E8529D95A4E730A7AB4A3E8F8A8AF979A665EAFD465FC64A0C5F8F3F9003489415899D59A543D8208C54A3166529B53922D4EC143B50F01423B177895EDEE22BB739F647ECF85F50BC25EF7B5A725DEE868626ED79D451140800E03B59B956F8210E556067407D13DC90FA9E8B872BFB8F")
   181  	dk, err := mlkem768.NewKeyFromExtendedEncoding(dkBytes)
   182  	if err != nil {
   183  		t.Fatal(err)
   184  	}
   185  	ct, _ := hex.DecodeString("B52C56B92A4B7CE9E4CB7C5B1B163167A8A1675B2FDEF84A5B67CA15DB694C9F11BD027C30AE22EC921A1D911599AF0585E48D20DA70DF9F39E32EF95D4C8F44BFEFDAA5DA64F1054631D04D6D3CFD0A540DD7BA3886E4B5F13E878788604C95C096EAB3919F427521419A946C26CC041475D7124CDC01D0373E5B09C7A70603CFDB4FB3405023F2264DC3F983C4FC02A2D1B268F2208A1F6E2A6209BFF12F6F465F0B069C3A7F84F606D8A94064003D6EC114C8E808D3053884C1D5A142FBF20112EB360FDA3F0F28B172AE50F5E7D83801FB3F0064B687187074BD7FE30EDDAA334CF8FC04FA8CED899CEADE4B4F28B68372BAF98FF482A415B731155B75CEB976BE0EA0285BA01A27F1857A8FB377A3AE0C23B2AA9A079BFABFF0D5B2F1CD9B718BEA03C42F343A39B4F142D01AD8ACBB50E38853CF9A50C8B44C3CF671A4A9043B26DDBB24959AD6715C08521855C79A23B9C3D6471749C40725BDD5C2776D43AED20204BAA141EFB3304917474B7F9F7A4B08B1A93DAED98C67495359D37D67F7438BEE5E43585634B26C6B3810D7CDCBC0F6EB877A6087E68ACB8480D3A8CF6900447E49B417F15A53B607A0E216B855970D37406870B4568722DA77A4084703816784E2F16BED18996532C5D8B7F5D214464E5F3F6E905867B0CE119E252A66713253544685D208E1723908A0CE97834652E08AE7BDC881A131B73C71E84D20D68FDEFF4F5D70CD1AF57B78E3491A9865942321800A203C05ED1FEEB5A28E584E19F6535E7F84E4A24F84A72DCAF5648B4A4235DD664464482F03176E888C28BFC6C1CB238CFFA35A321E71791D9EA8ED0878C61121BF8D2A4AB2C1A5E120BC40ABB1892D1715090A0EE48252CA297A99AA0E510CF26B1ADD06CA543E1C5D6BDCD3B9C585C8538045DB5C252EC3C8C3C954D9BE5907094A894E60EAB43538CFEE82E8FFC0791B0D0F43AC1627830A61D56DAD96C62958B0DE780B78BD47A604550DAB83FFF227C324049471F35248CFB849B25724FF704D5277AA352D550958BE3B237DFF473EC2ADBAEA48CA2658AEFCC77BBD4264AB374D70EAE5B964416CE8226A7E3255A0F8D7E2ADCA062BCD6D78D60D1B32E11405BE54B66EF0FDDD567702A3BCCFEDE3C584701269ED14809F06F8968356BB9267FE86E514252E88BB5C30A7ECB3D0E621021EE0FBF7871B09342BF84F55C97EAF86C48189C7FF4DF389F077E2806E5FA73B3E9458A16C7E275F4F602275580EB7B7135FB537FA0CD95D6EA58C108CD8943D70C1643111F4F01CA8A8276A902666ED81B78D168B006F16AAA3D8E4CE4F4D0FB0997E41AEFFB5B3DAA838732F357349447F387776C793C0479DE9E99498CC356FDB0075A703F23C55D47B550EC89B02ADE89329086A50843456FEDC3788AC8D97233C54560467EE1D0F024B18428F0D73B30E19F5C63B9ABF11415BEA4D0170130BAABD33C05E6524E5FB5581B22B0433342248266D0F1053B245CC2462DC44D34965102482A8ED9E4E964D5683E5D45D0C8269")
   186  	ss, err := kyberDecapsulate(dk, ct)
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	exp, _ := hex.DecodeString("914CB67FE5C38E73BF74181C0AC50428DEDF7750A98058F7D536708774535B29")
   191  	if !bytes.Equal(ss, exp) {
   192  		t.Fatalf("got %x, want %x", ss, exp)
   193  	}
   194  }
   195  
   196  func TestKyberEncapsulate(t *testing.T) {
   197  	dk, err := mlkem768.GenerateKey()
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	ct, ss, err := kyberEncapsulate(dk.EncapsulationKey())
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  	dkSS, err := kyberDecapsulate(dk, ct)
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  	if !bytes.Equal(ss, dkSS) {
   210  		t.Fatalf("got %x, want %x", ss, dkSS)
   211  	}
   212  }
   213  

View as plain text